Refactor architecture, fix all linter issues, and implement specification features (5 tabs, issue dropdowns, contact, info, search, pdf)
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import '../models/post_item.dart';
|
||||
import '../services/pdf_service.dart';
|
||||
|
||||
class DetailScreen extends StatelessWidget {
|
||||
final PostItem item;
|
||||
|
||||
const DetailScreen({super.key, required this.item});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final formattedDate =
|
||||
DateFormat('dd.MM.yyyy HH:mm').format(item.createdDate);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(item.title, overflow: TextOverflow.ellipsis),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.picture_as_pdf),
|
||||
tooltip: 'Als PDF drucken / teilen',
|
||||
onPressed: () => PdfService.printSinglePost(item),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (item.imageUrls.isNotEmpty)
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: item.imageUrls.first,
|
||||
width: double.infinity,
|
||||
fit: BoxFit.cover,
|
||||
placeholder: (context, url) => const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(32.0),
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
errorWidget: (context, url, error) => Container(
|
||||
height: 180,
|
||||
color: Colors.grey.shade200,
|
||||
child: const Icon(Icons.image_not_supported, size: 48),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
item.title,
|
||||
style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
const Icon(Icons.calendar_today, size: 16, color: Colors.grey),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
formattedDate,
|
||||
style: TextStyle(fontSize: 13, color: Colors.grey.shade700),
|
||||
),
|
||||
if (item.status != null) ...[
|
||||
const Spacer(),
|
||||
Container(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue.shade50,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: Colors.blue.shade200),
|
||||
),
|
||||
child: Text(
|
||||
item.status!,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.blue.shade800),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
if (item.street != null && item.street!.isNotEmpty) ...[
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
const Icon(Icons.location_on, size: 16, color: Colors.redAccent),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
'Örtlichkeit: ${item.street}',
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
if (item.category != null && item.category!.isNotEmpty) ...[
|
||||
const SizedBox(height: 6),
|
||||
Row(
|
||||
children: [
|
||||
const Icon(Icons.category, size: 16, color: Colors.orange),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
'Kategorie: ${item.category}',
|
||||
style: TextStyle(color: Colors.grey.shade800),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 16),
|
||||
const Divider(),
|
||||
const SizedBox(height: 12),
|
||||
const Text(
|
||||
'Beschreibung',
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
item.description,
|
||||
style: const TextStyle(fontSize: 15, height: 1.5),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
// Additional images gallery if there are multiple images
|
||||
if (item.imageUrls.length > 1) ...[
|
||||
const Text(
|
||||
'Weitere Fotos',
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(
|
||||
height: 120,
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: item.imageUrls.length - 1,
|
||||
separatorBuilder: (ctx, i) => const SizedBox(width: 8),
|
||||
itemBuilder: (ctx, index) {
|
||||
final url = item.imageUrls[index + 1];
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: url,
|
||||
width: 120,
|
||||
height: 120,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user