fix(#156): caler la modale AM sur les TF et unifier create/review.

ValidationFormMetrics (titres, TF, écarts) pilote la hauteur ; photo
étirée sur le corps ; mêmes widgets create et validation.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-23 16:49:59 +02:00
co-authored by Cursor
parent e3552667bc
commit 8ee2ca8ea6
5 changed files with 272 additions and 162 deletions
@@ -76,6 +76,10 @@ class AmDossierWizard extends StatefulWidget {
bool get isCreate => mode == AmDossierWizardMode.create;
/// Hauteur corps modale AM — dérivée de [ValidationFormMetrics] (4 lignes).
static double get shellBodyHeight =>
ValidationFormMetrics.shellBodyHeightForRows(4);
@override
State<AmDossierWizard> createState() => _AmDossierWizardState();
}
@@ -584,56 +588,45 @@ class _AmDossierWizardState extends State<AmDossierWizard> {
Widget _buildStep0() {
if (_isCreate) {
return LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minWidth: constraints.maxWidth),
child: IdentityBlock.editable(
title: 'Identité et coordonnées',
nomController: _nomCtrl,
prenomController: _prenomCtrl,
telephoneController: _telCtrl,
emailController: _emailCtrl,
adresseController: _adresseCtrl,
codePostalController: _cpCtrl,
villeController: _villeCtrl,
),
),
);
},
return IdentityBlock.editable(
title: 'Identité et coordonnées',
nomController: _nomCtrl,
prenomController: _prenomCtrl,
telephoneController: _telCtrl,
emailController: _emailCtrl,
adresseController: _adresseCtrl,
codePostalController: _cpCtrl,
villeController: _villeCtrl,
);
}
final u = _dossier.user;
return LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minWidth: constraints.maxWidth),
child: IdentityBlock.readOnlyFromUser(
u,
title: 'Identité et coordonnées',
emptyLabel: '',
),
),
);
},
return IdentityBlock.readOnlyFromUser(
u,
title: 'Identité et coordonnées',
emptyLabel: '',
);
}
Widget _buildStep1() {
// Modale calée sur les TF ; photo étirée sur toute la hauteur utile
// (largeur = [AdminAmPhotoFrame.columnWidthForHeight], cadre inclus).
return LayoutBuilder(
builder: (context, c) {
final maxRowW = c.maxWidth;
final maxRowH = c.maxHeight;
const photoHeaderH = 0.0;
final bodyH = (maxRowH - photoHeaderH).clamp(0.0, double.infinity);
final idealPhotoW = bodyH * _idPhotoAspectRatio + 16;
final maxRowH = c.maxHeight.clamp(0.0, double.infinity);
final maxPhotoW = (maxRowW - _photoProGap - _proColumnMinWidth)
.clamp(0.0, double.infinity);
var photoW = idealPhotoW.clamp(_photoColumnMinWidth, 360.0);
var photoW = AdminAmPhotoFrame.columnWidthForHeight(maxRowH)
.clamp(_photoColumnMinWidth, 360.0);
if (photoW > maxPhotoW) photoW = maxPhotoW;
photoW = photoW.clamp(0.0, maxRowW - _photoProGap);
final form = _isCreate
? _buildCreateProFields()
: ValidationDetailSection(
title: 'Dossier professionnel',
fields: _photoProFields(_dossier),
rowLayout: _photoProRowLayout,
);
return Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
@@ -651,22 +644,9 @@ class _AmDossierWizardState extends State<AmDossierWizard> {
),
const SizedBox(width: _photoProGap),
Expanded(
child: LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints:
BoxConstraints(minWidth: constraints.maxWidth),
child: _isCreate
? _buildCreateProFields()
: ValidationDetailSection(
title: 'Dossier professionnel',
fields: _photoProFields(_dossier),
rowLayout: _photoProRowLayout,
),
),
);
},
child: Align(
alignment: Alignment.topCenter,
child: form,
),
),
],