release: squash merge develop → master
Quotidien / Epic C : feed bulles parent (#173), module Cartes (#194/#195), evenements_agenda (#205), couples garde AM (#169–#171), API absences (#172). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:p_tits_pas/models/couple_garde.dart';
|
||||
import 'package:p_tits_pas/services/api/api_config.dart';
|
||||
import 'package:p_tits_pas/widgets/common/auth_network_image.dart';
|
||||
import 'package:p_tits_pas/widgets/quotidien/carte.dart';
|
||||
import 'package:p_tits_pas/widgets/quotidien/quotidien_theme.dart';
|
||||
|
||||
/// Rôle qui consulte le bandeau : côté parent (enfant | nounou) ou côté AM
|
||||
@@ -37,7 +38,7 @@ class CoupleSelectorBandeau extends StatelessWidget {
|
||||
|
||||
CoupleGarde? get _selected {
|
||||
if (couples.isEmpty) return null;
|
||||
if (selectedCoupleId != null) {
|
||||
if (selectedCoupleId != null) {
|
||||
for (final c in couples) {
|
||||
if (c.id == selectedCoupleId) return c;
|
||||
}
|
||||
@@ -133,16 +134,51 @@ class _CoupleCard extends StatelessWidget {
|
||||
required this.colorIndex,
|
||||
});
|
||||
|
||||
/// Libellé parents côté AM : « Sophie » ou « Thomas et Claire ».
|
||||
static String _parentsLabel(List<CoupleMembre> parents) {
|
||||
if (parents.isEmpty) return 'Parents';
|
||||
String prenomOf(CoupleMembre p) {
|
||||
final prenom = (p.prenom ?? '').trim();
|
||||
if (prenom.isNotEmpty) return prenom;
|
||||
return p.displayName(fallback: 'Parent');
|
||||
}
|
||||
if (parents.length == 1) return prenomOf(parents.first);
|
||||
return '${prenomOf(parents[0])} et ${prenomOf(parents[1])}';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 90,
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage(QuotidienTheme.bandeauColors[colorIndex % QuotidienTheme.bandeauColors.length]),
|
||||
fit: BoxFit.fill,
|
||||
// Parent mode: enfant | AM (photo + prénom)
|
||||
// AM mode: enfant | parent(s) — texte seul, pas de vignette parent
|
||||
final isParentMode = mode == CoupleBandeauMode.parent;
|
||||
|
||||
Widget amOrParentsWidget;
|
||||
|
||||
if (isParentMode) {
|
||||
amOrParentsWidget = _MembreTile(
|
||||
photoUrl: couple.am?.photoUrl,
|
||||
name: (couple.am?.prenom != null && couple.am!.prenom!.isNotEmpty)
|
||||
? couple.am!.prenom!
|
||||
: (couple.am?.displayName(fallback: 'Nounou') ?? 'Nounou'),
|
||||
fallbackIcon: Icons.volunteer_activism,
|
||||
);
|
||||
} else {
|
||||
amOrParentsWidget = Text(
|
||||
_parentsLabel(couple.parents),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: GoogleFonts.merienda(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: QuotidienTheme.ink,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Carte.bandeau(
|
||||
assetPath: QuotidienTheme
|
||||
.bandeauColors[colorIndex % QuotidienTheme.bandeauColors.length],
|
||||
height: 90,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Row(
|
||||
children: [
|
||||
@@ -151,7 +187,8 @@ class _CoupleCard extends StatelessWidget {
|
||||
padding: const EdgeInsets.only(right: 12),
|
||||
child: _MembreTile(
|
||||
photoUrl: couple.enfant.photoUrl,
|
||||
name: (couple.enfant.prenom != null && couple.enfant.prenom!.isNotEmpty)
|
||||
name: (couple.enfant.prenom != null &&
|
||||
couple.enfant.prenom!.isNotEmpty)
|
||||
? couple.enfant.prenom!
|
||||
: couple.enfant.displayName(fallback: 'Enfant'),
|
||||
fallbackIcon: Icons.child_care,
|
||||
@@ -171,29 +208,17 @@ class _CoupleCard extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 12),
|
||||
child: _MembreTile(
|
||||
photoUrl: couple.am.photoUrl,
|
||||
name: (couple.am.prenom != null && couple.am.prenom!.isNotEmpty)
|
||||
? couple.am.prenom!
|
||||
: couple.am.displayName(
|
||||
fallback: mode == CoupleBandeauMode.parent
|
||||
? 'Nounou'
|
||||
: 'Parent',
|
||||
),
|
||||
fallbackIcon: mode == CoupleBandeauMode.parent
|
||||
? Icons.volunteer_activism
|
||||
: Icons.person_outline,
|
||||
),
|
||||
child: amOrParentsWidget,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 28,
|
||||
child: showChevron
|
||||
? const Icon(
|
||||
Icons.keyboard_arrow_down,
|
||||
color: QuotidienTheme.ink,
|
||||
)
|
||||
: null,
|
||||
child: showChevron
|
||||
? const Icon(
|
||||
Icons.keyboard_arrow_down,
|
||||
color: QuotidienTheme.ink,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -279,24 +304,22 @@ class _CoupleBandeauSkeleton extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 90,
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: const AssetImage(QuotidienTheme.bandeauLime), // Un asset existant
|
||||
fit: BoxFit.fill,
|
||||
colorFilter: ColorFilter.mode(
|
||||
Colors.white.withValues(alpha: 0.5),
|
||||
BlendMode.lighten,
|
||||
return ColorFiltered(
|
||||
colorFilter: ColorFilter.mode(
|
||||
Colors.white.withValues(alpha: 0.5),
|
||||
BlendMode.lighten,
|
||||
),
|
||||
child: Carte.bandeau(
|
||||
assetPath: QuotidienTheme.bandeauLime,
|
||||
height: 90,
|
||||
child: const Center(
|
||||
child: SizedBox(
|
||||
width: 26,
|
||||
height: 26,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
),
|
||||
),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: const SizedBox(
|
||||
width: 26,
|
||||
height: 26,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -306,14 +329,9 @@ class _CoupleBandeauEmpty extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
return Carte.bandeau(
|
||||
assetPath: QuotidienTheme.bandeauLime,
|
||||
height: 90,
|
||||
decoration: const BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage(QuotidienTheme.bandeauLime), // Un asset existant par défaut
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Row(
|
||||
children: [
|
||||
@@ -342,38 +360,35 @@ class _CoupleBandeauError extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 90,
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: const AssetImage(QuotidienTheme.bandeauLime), // Un asset existant
|
||||
fit: BoxFit.fill,
|
||||
colorFilter: ColorFilter.mode(
|
||||
QuotidienTheme.coral.withValues(alpha: 0.3),
|
||||
BlendMode.srcATop,
|
||||
),
|
||||
),
|
||||
return ColorFiltered(
|
||||
colorFilter: ColorFilter.mode(
|
||||
QuotidienTheme.coral.withValues(alpha: 0.3),
|
||||
BlendMode.srcATop,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.error_outline, color: QuotidienTheme.ink),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
message,
|
||||
style: GoogleFonts.merriweather(
|
||||
fontSize: 13,
|
||||
color: QuotidienTheme.ink,
|
||||
child: Carte.bandeau(
|
||||
assetPath: QuotidienTheme.bandeauLime,
|
||||
height: 90,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.error_outline, color: QuotidienTheme.ink),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
message,
|
||||
style: GoogleFonts.merriweather(
|
||||
fontSize: 13,
|
||||
color: QuotidienTheme.ink,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (onRetry != null)
|
||||
TextButton(
|
||||
onPressed: onRetry,
|
||||
child: const Text('Réessayer'),
|
||||
),
|
||||
],
|
||||
if (onRetry != null)
|
||||
TextButton(
|
||||
onPressed: onRetry,
|
||||
child: const Text('Réessayer'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user