Files
prosappweb/lib/ui/views/schedule_view.dart
T
Lizandro GuarnizoandClaude Sonnet 4.6 7451b7c57b feat: apply default hours (08:00-18:00) when enabling a schedule day
When a day is toggled on and has no hours set yet, automatically
apply continuous-day defaults (08:00 - 18:00) so the user can
save immediately without having to pick times manually.
Also clear fp.profesional in initState to ensure fresh data loads.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 23:08:23 -05:00

564 lines
26 KiB
Dart

import 'package:prosapp_web_app/models/usuario.dart';
import 'package:prosapp_web_app/providers/auth_provider.dart';
import 'package:prosapp_web_app/providers/professional_form_provider.dart';
import 'package:prosapp_web_app/providers/professional_provider.dart';
import 'package:prosapp_web_app/providers/profile_form_provider.dart';
import 'package:prosapp_web_app/router/router.dart';
import 'package:prosapp_web_app/services/navigation_service.dart';
import 'package:prosapp_web_app/ui/cards/white_card.dart';
import 'package:flutter/material.dart';
import 'package:prosapp_web_app/ui/shared/widgets/schedule_day_tile.dart';
import 'package:provider/provider.dart';
class ScheduleView extends StatefulWidget {
const ScheduleView({super.key});
@override
State<ScheduleView> createState() => _ScheduleViewState();
}
class _ScheduleViewState extends State<ScheduleView> {
Usuario? user;
late ProfessionalFormProvider professionalFormProvider;
@override
void initState() {
super.initState();
final authProvider = Provider.of<AuthProvider>(context, listen: false);
final profileFormProvider =
Provider.of<ProfileFormProvider>(context, listen: false);
professionalFormProvider =
Provider.of<ProfessionalFormProvider>(context, listen: false);
final proProvider =
Provider.of<ProfessionalProvider>(context, listen: false);
profileFormProvider.user = authProvider.user;
professionalFormProvider.clear();
proProvider.getProfessional(authProvider.user!.id).then((value) {
professionalFormProvider.setProfesional(value);
});
profileFormProvider.user = authProvider.user;
setState(() {
user = authProvider.user;
});
}
bool isTimeRangeValid(TimeOfDay startTime, TimeOfDay endTime) {
final start = DateTime(2024, 1, 1, startTime.hour, startTime.minute);
final end = DateTime(2024, 1, 1, endTime.hour, endTime.minute);
return start.isBefore(end);
}
@override
Widget build(BuildContext context) {
final profileFormProvider = Provider.of<ProfileFormProvider>(context);
final user = profileFormProvider.user!;
return Consumer<ProfessionalFormProvider>(
builder: (context, professionalFormProvider, child) {
if (professionalFormProvider.profesional == null) {
return const Center(
child: CircularProgressIndicator(),
);
}
final profesional = professionalFormProvider.profesional!;
return ListView(
physics: const ClampingScrollPhysics(),
children: [
Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 900),
child: WhiteCard(
title: 'Horario',
child: Column(
children: [
ScheduleDayTile(
day: 'Lunes',
schedule: profesional.schedules.monday,
onEnableChanged: (value) {
setState(() {
final cur = profesional.schedules.monday;
final updated = (value && cur.range1Hour1 == null)
? cur.copyWith(enabled: true, continuousDay: true, range1Hour1: const TimeOfDay(hour: 8, minute: 0), range2Hour2: const TimeOfDay(hour: 18, minute: 0))
: cur.copyWith(enabled: value);
professionalFormProvider.copyProfesionalWith(schedules: profesional.schedules.copyWith(monday: updated));
});
},
onContinuousDayChanged: (value) {
setState(() {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
monday: profesional.schedules.monday.copyWith(
continuousDay: value,
),
),
);
});
},
onRange1Hour1Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
monday: profesional.schedules.monday.copyWith(
range1Hour1: pickedTime,
),
),
);
},
onRange1Hour2Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
monday: profesional.schedules.monday.copyWith(
range1Hour2: pickedTime,
),
),
);
},
onRange2Hour1Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
monday: profesional.schedules.monday.copyWith(
range2Hour1: pickedTime,
),
),
);
},
onRange2Hour2Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
monday: profesional.schedules.monday.copyWith(
range2Hour2: pickedTime,
),
),
);
},
),
const Divider(
height: 20,
),
ScheduleDayTile(
day: 'Martes',
schedule: profesional.schedules.tuesday,
onEnableChanged: (value) {
setState(() {
final cur = profesional.schedules.tuesday;
final updated = (value && cur.range1Hour1 == null)
? cur.copyWith(enabled: true, continuousDay: true, range1Hour1: const TimeOfDay(hour: 8, minute: 0), range2Hour2: const TimeOfDay(hour: 18, minute: 0))
: cur.copyWith(enabled: value);
professionalFormProvider.copyProfesionalWith(schedules: profesional.schedules.copyWith(tuesday: updated));
});
},
onContinuousDayChanged: (value) {
setState(() {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
tuesday: profesional.schedules.tuesday.copyWith(
continuousDay: value,
),
),
);
});
},
onRange1Hour1Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
tuesday: profesional.schedules.tuesday.copyWith(
range1Hour1: pickedTime,
),
),
);
},
onRange1Hour2Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
tuesday: profesional.schedules.tuesday.copyWith(
range1Hour2: pickedTime,
),
),
);
},
onRange2Hour1Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
tuesday: profesional.schedules.tuesday.copyWith(
range2Hour1: pickedTime,
),
),
);
},
onRange2Hour2Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
tuesday: profesional.schedules.tuesday.copyWith(
range2Hour2: pickedTime,
),
),
);
},
),
const Divider(
height: 20,
),
ScheduleDayTile(
day: 'Miercoles',
schedule: profesional.schedules.wednesday,
onEnableChanged: (value) {
setState(() {
final cur = profesional.schedules.wednesday;
final updated = (value && cur.range1Hour1 == null)
? cur.copyWith(enabled: true, continuousDay: true, range1Hour1: const TimeOfDay(hour: 8, minute: 0), range2Hour2: const TimeOfDay(hour: 18, minute: 0))
: cur.copyWith(enabled: value);
professionalFormProvider.copyProfesionalWith(schedules: profesional.schedules.copyWith(wednesday: updated));
});
},
onContinuousDayChanged: (value) {
setState(() {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
wednesday:
profesional.schedules.wednesday.copyWith(
continuousDay: value,
),
),
);
});
},
onRange1Hour1Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
wednesday: profesional.schedules.wednesday.copyWith(
range1Hour1: pickedTime,
),
),
);
},
onRange1Hour2Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
wednesday: profesional.schedules.wednesday.copyWith(
range1Hour2: pickedTime,
),
),
);
},
onRange2Hour1Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
wednesday: profesional.schedules.wednesday.copyWith(
range2Hour1: pickedTime,
),
),
);
},
onRange2Hour2Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
wednesday: profesional.schedules.wednesday.copyWith(
range2Hour2: pickedTime,
),
),
);
},
),
const Divider(
height: 20,
),
ScheduleDayTile(
day: 'Jueves',
schedule: profesional.schedules.thursday,
onEnableChanged: (value) {
setState(() {
final cur = profesional.schedules.thursday;
final updated = (value && cur.range1Hour1 == null)
? cur.copyWith(enabled: true, continuousDay: true, range1Hour1: const TimeOfDay(hour: 8, minute: 0), range2Hour2: const TimeOfDay(hour: 18, minute: 0))
: cur.copyWith(enabled: value);
professionalFormProvider.copyProfesionalWith(schedules: profesional.schedules.copyWith(thursday: updated));
});
},
onContinuousDayChanged: (value) {
setState(() {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
thursday: profesional.schedules.thursday.copyWith(
continuousDay: value,
),
),
);
});
},
onRange1Hour1Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
thursday: profesional.schedules.thursday.copyWith(
range1Hour1: pickedTime,
),
),
);
},
onRange1Hour2Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
thursday: profesional.schedules.thursday.copyWith(
range1Hour2: pickedTime,
),
),
);
},
onRange2Hour1Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
thursday: profesional.schedules.thursday.copyWith(
range2Hour1: pickedTime,
),
),
);
},
onRange2Hour2Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
thursday: profesional.schedules.thursday.copyWith(
range2Hour2: pickedTime,
),
),
);
},
),
const Divider(
height: 20,
),
ScheduleDayTile(
day: 'Viernes',
schedule: profesional.schedules.friday,
onEnableChanged: (value) {
setState(() {
final cur = profesional.schedules.friday;
final updated = (value && cur.range1Hour1 == null)
? cur.copyWith(enabled: true, continuousDay: true, range1Hour1: const TimeOfDay(hour: 8, minute: 0), range2Hour2: const TimeOfDay(hour: 18, minute: 0))
: cur.copyWith(enabled: value);
professionalFormProvider.copyProfesionalWith(schedules: profesional.schedules.copyWith(friday: updated));
});
},
onContinuousDayChanged: (value) {
setState(() {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
friday: profesional.schedules.friday.copyWith(
continuousDay: value,
),
),
);
});
},
onRange1Hour1Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
friday: profesional.schedules.friday.copyWith(
range1Hour1: pickedTime,
),
),
);
},
onRange1Hour2Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
friday: profesional.schedules.friday.copyWith(
range1Hour2: pickedTime,
),
),
);
},
onRange2Hour1Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
friday: profesional.schedules.friday.copyWith(
range2Hour1: pickedTime,
),
),
);
},
onRange2Hour2Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
friday: profesional.schedules.friday.copyWith(
range2Hour2: pickedTime,
),
),
);
},
),
const Divider(
height: 20,
),
ScheduleDayTile(
day: 'Sabado',
schedule: profesional.schedules.saturday,
onEnableChanged: (value) {
setState(() {
final cur = profesional.schedules.saturday;
final updated = (value && cur.range1Hour1 == null)
? cur.copyWith(enabled: true, continuousDay: true, range1Hour1: const TimeOfDay(hour: 8, minute: 0), range2Hour2: const TimeOfDay(hour: 18, minute: 0))
: cur.copyWith(enabled: value);
professionalFormProvider.copyProfesionalWith(schedules: profesional.schedules.copyWith(saturday: updated));
});
},
onContinuousDayChanged: (value) {
setState(() {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
saturday: profesional.schedules.saturday.copyWith(
continuousDay: value,
),
),
);
});
},
onRange1Hour1Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
saturday: profesional.schedules.saturday.copyWith(
range1Hour1: pickedTime,
),
),
);
},
onRange1Hour2Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
saturday: profesional.schedules.saturday.copyWith(
range1Hour2: pickedTime,
),
),
);
},
onRange2Hour1Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
saturday: profesional.schedules.saturday.copyWith(
range2Hour1: pickedTime,
),
),
);
},
onRange2Hour2Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
saturday: profesional.schedules.saturday.copyWith(
range2Hour2: pickedTime,
),
),
);
},
),
const Divider(
height: 20,
),
ScheduleDayTile(
day: 'Domingo',
schedule: profesional.schedules.sunday,
onEnableChanged: (value) {
setState(() {
final cur = profesional.schedules.sunday;
final updated = (value && cur.range1Hour1 == null)
? cur.copyWith(enabled: true, continuousDay: true, range1Hour1: const TimeOfDay(hour: 8, minute: 0), range2Hour2: const TimeOfDay(hour: 18, minute: 0))
: cur.copyWith(enabled: value);
professionalFormProvider.copyProfesionalWith(schedules: profesional.schedules.copyWith(sunday: updated));
});
},
onContinuousDayChanged: (value) {
setState(() {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
sunday: profesional.schedules.sunday.copyWith(
continuousDay: value,
),
),
);
});
},
onRange1Hour1Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
sunday: profesional.schedules.sunday.copyWith(
range1Hour1: pickedTime,
),
),
);
},
onRange1Hour2Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
sunday: profesional.schedules.sunday.copyWith(
range1Hour2: pickedTime,
),
),
);
},
onRange2Hour1Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
sunday: profesional.schedules.sunday.copyWith(
range2Hour1: pickedTime,
),
),
);
},
onRange2Hour2Pick: (pickedTime) {
professionalFormProvider.copyProfesionalWith(
schedules: profesional.schedules.copyWith(
sunday: profesional.schedules.sunday.copyWith(
range2Hour2: pickedTime,
),
),
);
},
),
const Divider(
height: 20,
),
Container(
margin: const EdgeInsets.only(top: 10),
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 130),
child: ElevatedButton(
onPressed: () async {
await professionalFormProvider.updateProfesionalProfileScheduleInfo(user.id);
NavigationService.replaceTo(Flurorouter.professionalProfileRoute);
},
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(
Colors.blue.shade400,
),
shape: WidgetStateProperty.all(
const RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(5)),
)),
shadowColor:
WidgetStateProperty.all(Colors.transparent),
),
child: const Text('Guardar',
style: TextStyle(color: Colors.white)),
),
),
),
const SizedBox(height: 10),
],
),
),
),
),
],
);
});
}
}