Files
kulakpos_app/lib/Screens/hrm/holiday/add_new_holiday.dart

281 lines
10 KiB
Dart
Raw Permalink Normal View History

2026-02-07 15:57:09 +07:00
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; // Import Riverpod
import 'package:iconly/iconly.dart';
import 'package:intl/intl.dart';
import 'package:mobile_pos/generated/l10n.dart' as lang;
import '../../../constant.dart';
// --- Riverpod Imports (Assuming these paths are correct) ---
import 'package:mobile_pos/Screens/hrm/holiday/model/holiday_list_model.dart';
import 'package:mobile_pos/Screens/hrm/holiday/repo/holiday_repo.dart';
// -----------------------------------------------------------
// Accept optional HolidayData for editing (renamed from isEdit)
class AddNewHoliday extends ConsumerStatefulWidget {
final HolidayData? holidayData;
// Changed constructor to use key and remove isEdit
const AddNewHoliday({super.key, this.holidayData});
@override
ConsumerState<AddNewHoliday> createState() => _AddNewHolidayState();
}
class _AddNewHolidayState extends ConsumerState<AddNewHoliday> {
final nameController = TextEditingController();
final startDateController = TextEditingController();
final endDateController = TextEditingController();
final descriptionController = TextEditingController();
final GlobalKey<FormState> _key = GlobalKey();
// Variables to hold parsed dates for comparison/API formatting
DateTime? _selectedStartDate;
DateTime? _selectedEndDate;
bool get isEditing => widget.holidayData != null;
final DateFormat _displayFormat = DateFormat('dd/MM/yyyy');
final DateFormat _apiFormat = DateFormat('yyyy-MM-dd'); // API typically needs YYYY-MM-DD
@override
void initState() {
super.initState();
if (isEditing) {
final holiday = widget.holidayData!;
nameController.text = holiday.name ?? '';
descriptionController.text = holiday.description ?? '';
try {
if (holiday.startDate != null) {
_selectedStartDate = DateTime.parse(holiday.startDate!);
startDateController.text = _displayFormat.format(_selectedStartDate!);
}
if (holiday.endDate != null) {
_selectedEndDate = DateTime.parse(holiday.endDate!);
endDateController.text = _displayFormat.format(_selectedEndDate!);
}
} catch (e) {
// Handle date parsing failure if API format is inconsistent
debugPrint('Error parsing date for editing: $e');
startDateController.text = holiday.startDate ?? '';
endDateController.text = holiday.endDate ?? '';
}
}
}
@override
void dispose() {
nameController.dispose();
startDateController.dispose();
endDateController.dispose();
descriptionController.dispose();
super.dispose();
}
Future<void> _selectDate(BuildContext context, TextEditingController controller, bool isStart) async {
DateTime initialDate = DateTime.now();
if (isStart) {
initialDate = _selectedStartDate ?? initialDate;
} else {
initialDate = _selectedEndDate ?? _selectedStartDate ?? initialDate;
}
final DateTime? picked = await showDatePicker(
initialDate: initialDate,
firstDate: DateTime(2015, 8),
lastDate: DateTime(2101),
context: context,
);
if (picked != null) {
setState(() {
controller.text = _displayFormat.format(picked);
if (isStart) {
_selectedStartDate = picked;
// Auto-adjust end date if it is before the new start date
if (_selectedEndDate != null && _selectedEndDate!.isBefore(picked)) {
_selectedEndDate = picked;
endDateController.text = _displayFormat.format(picked);
}
} else {
_selectedEndDate = picked;
}
});
}
}
void _submit() async {
if (_key.currentState!.validate()) {
// Validate that dates are not null and end date is not before start date
if (_selectedStartDate == null || _selectedEndDate == null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(lang.S.of(context).pleaseSelectValidStartAndEndDates)),
);
return;
}
if (_selectedEndDate!.isBefore(_selectedStartDate!)) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(lang.S.of(context).endDateCannotBeBeforeStartDate)),
);
return;
}
final repo = HolidayRepo();
final String apiStartDate = _apiFormat.format(_selectedStartDate!);
final String apiEndDate = _apiFormat.format(_selectedEndDate!);
if (isEditing) {
// --- UPDATE HOLIDAY ---
await repo.updateHolidays(
ref: ref,
context: context,
id: widget.holidayData!.id!.toInt(),
name: nameController.text,
startDate: apiStartDate,
endDate: apiEndDate,
description: descriptionController.text,
);
} else {
// --- CREATE HOLIDAY ---
await repo.createHolidays(
ref: ref,
context: context,
name: nameController.text,
startDate: apiStartDate,
endDate: apiEndDate,
description: descriptionController.text,
);
}
// Note: The repo functions already handle Navigator.pop(context) and SnackBar
}
}
@override
Widget build(BuildContext context) {
final _lang = lang.S.of(context);
return Scaffold(
backgroundColor: kWhite,
appBar: AppBar(
centerTitle: true,
title: Text(
isEditing ? _lang.editHoliday : _lang.addNewHoliday,
),
bottom: const PreferredSize(
preferredSize: Size.fromHeight(1),
child: Divider(
height: 2,
color: kBackgroundColor,
),
),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Form(
key: _key,
child: Column(
children: [
TextFormField(
controller: nameController,
decoration: InputDecoration(
labelText: _lang.name,
hintText: _lang.enterHolidayName,
),
validator: (value) => value!.isEmpty ? _lang.pleaseEnterHolidayName : null,
),
const SizedBox(height: 20),
Row(
children: [
Expanded(
child: TextFormField(
keyboardType: TextInputType.name,
readOnly: true,
controller: startDateController,
decoration: InputDecoration(
labelText: _lang.startDate,
hintText: _lang.pleaseEnterDate,
suffixIcon: IconButton(
padding: EdgeInsets.zero,
visualDensity: const VisualDensity(horizontal: -4, vertical: -4),
onPressed: () => _selectDate(context, startDateController, true),
icon: const Icon(IconlyLight.calendar, size: 22),
),
),
validator: (value) => value!.isEmpty ? _lang.pleaseSelectStartDate : null,
),
),
const SizedBox(width: 16),
Expanded(
child: TextFormField(
keyboardType: TextInputType.name,
readOnly: true,
controller: endDateController,
decoration: InputDecoration(
labelText: _lang.endDate,
hintText: _lang.pleaseEnterDate,
suffixIcon: IconButton(
padding: EdgeInsets.zero,
visualDensity: const VisualDensity(horizontal: -4, vertical: -4),
onPressed: () => _selectDate(context, endDateController, false),
icon: const Icon(IconlyLight.calendar, size: 22),
),
),
validator: (value) {
if (value!.isEmpty) {
return _lang.pleaseEnterEndDate;
}
if (_selectedStartDate != null &&
_selectedEndDate != null &&
_selectedEndDate!.isBefore(_selectedStartDate!)) {
return _lang.endDateBeforeStartDate;
}
return null;
},
),
),
],
),
const SizedBox(height: 20),
TextFormField(
controller: descriptionController,
decoration: InputDecoration(
labelText: _lang.description,
hintText: '${_lang.enterDescription}...',
),
),
const SizedBox(height: 20),
Row(
children: [
Expanded(
child: OutlinedButton(
onPressed: () {
// Reset functionality
setState(() {
_key.currentState?.reset();
nameController.clear();
descriptionController.clear();
startDateController.clear();
endDateController.clear();
_selectedStartDate = null;
_selectedEndDate = null;
});
},
child: Text(_lang.resets),
),
),
const SizedBox(width: 16),
Expanded(
child: ElevatedButton(
onPressed: _submit, // Call the submission function
child: Text(
isEditing ? _lang.update : _lang.save,
),
),
),
],
),
],
)),
),
);
}
}