import 'package:flutter/material.dart';
import '../../../app/theme.dart';
import '../../../core/identifiers/uuid.dart';
import '../../../shared/widgets/empty_state.dart';
import '../../../core/sync/master_data_sync_repository.dart';
import '../../customers/data/customer_store.dart';
import '../data/job_store.dart';
class JobsScreen extends StatelessWidget {
const JobsScreen({super.key});
Future<void> createJob(BuildContext context) async {
final number = TextEditingController(text: 'AUF-${DateTime.now().year}-');
final customer = TextEditingController();
final site = TextEditingController();
final address = TextEditingController();
String? selectedCustomerId;
final saved = await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: const Text('Neuer Auftrag'),
content: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 500),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: number,
decoration: const InputDecoration(
labelText: 'Auftragsnummer',
prefixIcon: Icon(Icons.tag_rounded),
border: OutlineInputBorder(),
),
),
const SizedBox(height: 14),
if (CustomerStore.instance.customers.isNotEmpty) ...[
DropdownButtonFormField<String>(
decoration: const InputDecoration(
labelText: 'Gespeicherten Kunden wählen',
prefixIcon: Icon(Icons.people_outline_rounded),
border: OutlineInputBorder(),
),
items: CustomerStore.instance.customers
.map(
(item) => DropdownMenuItem(
value: item.id,
child: Text(item.name),
),
)
.toList(),
onChanged: (id) {
final selected = CustomerStore.instance.customers
.firstWhere((item) => item.id == id);
customer.text = selected.name;
selectedCustomerId = selected.id;
if (address.text.isEmpty) address.text = selected.address;
},
),
const SizedBox(height: 14),
],
TextField(
controller: customer,
decoration: const InputDecoration(
labelText: 'Kunde',
prefixIcon: Icon(Icons.person_outline_rounded),
border: OutlineInputBorder(),
),
),
const SizedBox(height: 14),
TextField(
controller: site,
decoration: const InputDecoration(
labelText: 'Baustelle / Auftrag',
prefixIcon: Icon(Icons.work_outline_rounded),
border: OutlineInputBorder(),
),
),
const SizedBox(height: 14),
TextField(
controller: address,
decoration: const InputDecoration(
labelText: 'Adresse (optional)',
prefixIcon: Icon(Icons.location_on_outlined),
border: OutlineInputBorder(),
),
),
],
),
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('Abbrechen'),
),
FilledButton(
onPressed: () {
if (number.text.trim().isEmpty ||
customer.text.trim().isEmpty ||
site.text.trim().isEmpty) {
return;
}
Navigator.pop(context, true);
},
child: const Text('Auftrag speichern'),
),
],
),
);
if (saved == true) {
await JobStore.instance.add(
Job(
id: newUuid(),
number: number.text.trim(),
customer: customer.text.trim(),
site: site.text.trim(),
address: address.text.trim(),
customerId: selectedCustomerId,
siteId: newUuid(),
),
);
}
number.dispose();
customer.dispose();
site.dispose();
address.dispose();
}
Future<void> deleteJob(BuildContext context, Job job) async {
final confirmed = await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: const Text('Auftrag löschen?'),
content: Text('${job.number} · ${job.site} wird dauerhaft entfernt.'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('Abbrechen'),
),
FilledButton(
onPressed: () => Navigator.pop(context, true),
child: const Text('Löschen'),
),
],
),
);
if (confirmed == true) await JobStore.instance.remove(job.id);
}
@override
Widget build(BuildContext context) => ListenableBuilder(
listenable: JobStore.instance,
builder: (context, _) {
final jobs = JobStore.instance.jobs;
if (jobs.isEmpty) {
return Padding(
padding: const EdgeInsets.all(24),
child: EmptyState(
icon: Icons.work_outline_rounded,
title: 'Noch keine Aufträge',
description:
'Lege einen Auftrag an, um Baustelle und Kunde später direkt einem Nachweis zuzuordnen.',
actionLabel: 'Auftrag anlegen',
onPressed: () => createJob(context),
),
);
}
return SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 900),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Aufträge',
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 6),
Text(
'${jobs.length} lokal gespeichert',
style: Theme.of(context).textTheme.bodyLarge,
),
],
),
),
FilledButton.icon(
onPressed: () => createJob(context),
icon: const Icon(Icons.add_rounded),
label: const Text('Neu'),
),
],
),
const SizedBox(height: 24),
for (final job in jobs) ...[
Card(
child: ListTile(
contentPadding: const EdgeInsets.all(20),
leading: const CircleAvatar(
backgroundColor: AppColors.canvas,
child: Icon(
Icons.work_outline_rounded,
color: AppColors.green,
),
),
title: Text(
job.site,
style: const TextStyle(fontWeight: FontWeight.w800),
),
subtitle: Padding(
padding: const EdgeInsets.only(top: 6),
child: Text(
'${job.number} · ${job.customer}${job.address.isEmpty ? '' : '\n${job.address}'}\n${job.syncStatus.label}${job.syncError == null ? '' : ': ${job.syncError}'}',
),
),
trailing: IconButton(
tooltip: 'Auftrag löschen',
onPressed: () => deleteJob(context, job),
icon: const Icon(Icons.delete_outline_rounded),
),
),
),
const SizedBox(height: 12),
],
],
),
),
),
);
},
);
}
