manager-app/lib/Screens/Configurations/configurations_screen.dart
Thomas Fransolet 205f1ec933 Misc
2026-05-09 00:23:04 +02:00

280 lines
9.7 KiB
Dart

import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:manager_app/Components/common_loader.dart';
import 'package:manager_app/Components/string_input_container.dart';
import 'package:manager_app/l10n/app_localizations.dart';
import 'package:manager_app/Components/message_notification.dart';
import 'package:manager_app/Models/managerContext.dart';
import 'package:manager_app/Screens/Configurations/configuration_detail_screen.dart';
import 'package:manager_app/Screens/Configurations/new_configuration_popup.dart';
import 'package:manager_app/app_context.dart';
import 'package:manager_app/constants.dart';
import 'package:manager_api_new/api.dart';
import 'package:provider/provider.dart';
import 'package:intl/intl.dart';
import 'Section/section_detail_screen.dart';
import 'Section/SubSection/Menu/sub_section_edit_screen.dart';
class ConfigurationsScreen extends StatefulWidget {
ConfigurationsScreen({Key? key}) : super(key: key);
@override
_ConfigurationsScreenState createState() => _ConfigurationsScreenState();
}
class _ConfigurationsScreenState extends State<ConfigurationsScreen> {
ConfigurationDTO? selectedConfiguration;
String _filter = '';
Future<List<ConfigurationDTO>?>? _future;
void _refresh() => setState(() => _future = null);
@override
Widget build(BuildContext context) {
final appContext = Provider.of<AppContext>(context);
final Size size = MediaQuery.of(context).size;
final ManagerAppContext managerAppContext = appContext.getContext();
if (managerAppContext.selectedSubSection != null) {
return SubSectionEditScreen(
subSectionDTO: managerAppContext.selectedSubSection!,
rawData: managerAppContext.selectedSubSectionRawData!,
);
}
if (managerAppContext.selectedSection != null) {
return SectionDetailScreen(id: managerAppContext.selectedSection!.id!);
}
if (managerAppContext.selectedConfiguration != null) {
return ConfigurationDetailScreen(id: managerAppContext.selectedConfiguration!.id!);
}
_future ??= getConfigurations(managerAppContext);
return Align(
alignment: AlignmentDirectional.topCenter,
child: FutureBuilder(
future: _future,
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
var all = List<ConfigurationDTO>.from(snapshot.data);
if (managerAppContext.canEdit) all.add(ConfigurationDTO(id: null));
final filtered = _filter.isEmpty
? all
: all
.where((c) =>
c.id == null ||
(c.label?.toLowerCase().contains(_filter.toLowerCase()) ??
false))
.toList();
return _buildGrid(filtered, size, appContext, context);
} else if (snapshot.connectionState == ConnectionState.none) {
return Text(AppLocalizations.of(context)!.noData);
} else {
return Center(
child: Container(
height: size.height * 0.2,
child: CommonLoader(),
),
);
}
},
),
);
}
Widget _buildGrid(List<ConfigurationDTO> data, Size size, AppContext appContext,
BuildContext mainContext) {
return Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(12, 12, 12, 4),
child: Align(
alignment: Alignment.centerLeft,
child: SizedBox(
width: 280,
child: StringInputContainer(
label: AppLocalizations.of(context)!.searchLabel,
onChanged: (v) => setState(() => _filter = v),
),
),
),
),
Expanded(
child: GridView.builder(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 220,
childAspectRatio: 1.5,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
itemCount: data.length,
itemBuilder: (BuildContext context, int index) {
return _ConfigCard(
config: data[index],
onTap: () => _onTap(data[index], appContext, mainContext),
);
},
),
),
],
);
}
Future<void> _onTap(
ConfigurationDTO config, AppContext appContext, BuildContext mainContext) async {
if (config.id == null) {
var configurationToCreate = await showNewConfiguration(
appContext,
(bool refresh) {
if (refresh) _refresh();
},
context,
mainContext,
);
if (configurationToCreate != null && configurationToCreate.label != null) {
configurationToCreate.dateCreation = DateTime.now();
configurationToCreate.isOffline = false;
configurationToCreate.instanceId =
(appContext.getContext() as ManagerAppContext).instanceId;
await (appContext.getContext() as ManagerAppContext)
.clientAPI!
.configurationApi!
.configurationCreate(configurationToCreate);
final ctx = appContext.getContext() as ManagerAppContext;
ctx.selectedConfiguration = null;
await appContext.setContext(ctx);
showNotification(
kSuccess, kWhite, AppLocalizations.of(context)!.configCreatedSuccess, context, null);
_refresh();
}
} else {
setState(() {
final ctx = appContext.getContext() as ManagerAppContext;
ctx.selectedConfiguration = config;
selectedConfiguration = config;
});
}
}
}
class _ConfigCard extends StatefulWidget {
final ConfigurationDTO config;
final VoidCallback onTap;
const _ConfigCard({required this.config, required this.onTap});
@override
State<_ConfigCard> createState() => _ConfigCardState();
}
class _ConfigCardState extends State<_ConfigCard> {
bool _hovered = false;
@override
Widget build(BuildContext context) {
final config = widget.config;
final isAdd = config.id == null;
final hasImage = config.imageSource != null;
return MouseRegion(
onEnter: (_) => setState(() => _hovered = true),
onExit: (_) => setState(() => _hovered = false),
child: GestureDetector(
onTap: widget.onTap,
child: AnimatedScale(
scale: _hovered ? 1.03 : 1.0,
duration: const Duration(milliseconds: 150),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: kSecond,
spreadRadius: _hovered ? 1 : 0.5,
blurRadius: _hovered ? 10 : 5,
offset: const Offset(0, 2),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Stack(
fit: StackFit.expand,
children: [
// Background
if (!isAdd && hasImage)
Image.network(config.imageSource!, fit: BoxFit.cover)
else
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: isAdd
? [kSuccess, kSuccess.withOpacity(0.7)]
: [kPrimaryColor, kPrimaryColor.withOpacity(0.6)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
),
// Gradient scrim
if (!isAdd)
DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: const [0.35, 1.0],
colors: [
Colors.transparent,
Colors.black.withOpacity(0.65),
],
),
),
),
// Content
if (isAdd)
const Center(
child: Icon(Icons.add, color: kTextLightColor, size: 36),
)
else
Positioned(
left: 10,
right: 10,
bottom: 10,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
AutoSizeText(
config.label ?? '',
style: kCardTitleStyle,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
if (config.dateCreation != null)
Text(
DateFormat('dd/MM/yyyy').format(config.dateCreation!),
style: kCardSubtitleStyle,
),
],
),
),
],
),
),
),
),
),
);
}
}
Future<List<ConfigurationDTO>?> getConfigurations(
ManagerAppContext managerAppContext) async {
return managerAppContext.clientAPI!.configurationApi!
.configurationGet(instanceId: managerAppContext.instanceId);
}