import 'package:flutter/material.dart';
import '../../models/content_models.dart';
import '../../core/theme/app_theme.dart';
/// Shared taxonomy navigation for every discovery surface.
///
/// The widget deliberately receives only API `CategoryOption` values. It does
/// not know about FieldSchemas profiles, CPT-specific aliases or fallback
/// labels, so a screen cannot accidentally invent categories for its route.
class DiscoveryCategoryNavigation extends StatelessWidget {
const DiscoveryCategoryNavigation({
super.key,
required this.options,
required this.selectedSlug,
required this.allLabel,
required this.onSelected,
});
final List<CategoryOption> options;
final String selectedSlug;
final String allLabel;
final ValueChanged<String> onSelected;
@override
Widget build(BuildContext context) {
final usable = options
.where((option) => option.slug.isNotEmpty && option.name.isNotEmpty)
.toList(growable: false);
final roots = usable
.where((option) => option.isRoot)
.toList(growable: false);
if (roots.isEmpty) return const SizedBox.shrink();
CategoryOption? selected;
for (final option in usable) {
if (option.slug == selectedSlug) {
selected = option;
break;
}
}
final selectedRootSlug = selected == null
? (roots.any((option) => option.slug == selectedSlug)
? selectedSlug
: '')
: (selected.isRoot ? selected.slug : selected.parentSlug);
final children = selectedRootSlug.isEmpty
? const <CategoryOption>[]
: usable
.where((option) => option.parentSlug == selectedRootSlug)
.toList(growable: false);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_CategoryRow(
options: roots,
allLabel: allLabel,
allSelected: selectedSlug.isEmpty,
selectedSlug: selectedRootSlug,
onSelected: onSelected,
),
if (children.isNotEmpty) ...[
const SizedBox(height: 8),
_CategoryRow(
options: children,
selectedSlug: selectedSlug,
onSelected: onSelected,
),
],
],
);
}
}
class _CategoryRow extends StatelessWidget {
const _CategoryRow({
required this.options,
required this.selectedSlug,
required this.onSelected,
this.allLabel,
this.allSelected = false,
});
final List<CategoryOption> options;
final String selectedSlug;
final ValueChanged<String> onSelected;
final String? allLabel;
final bool allSelected;
@override
Widget build(BuildContext context) {
final palette = AppTheme.palette(context);
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
if (allLabel != null)
Padding(
padding: const EdgeInsets.only(right: 8),
child: ChoiceChip(
label: Text(allLabel!),
selected: allSelected,
onSelected: (_) => onSelected(''),
selectedColor: palette.brand,
labelStyle: TextStyle(
color: allSelected ? Colors.white : palette.ink,
fontWeight: allSelected ? FontWeight.w700 : FontWeight.w500,
),
side: BorderSide.none,
backgroundColor: Colors.white,
shape: const StadiumBorder(),
showCheckmark: false,
),
),
for (final option in options)
Padding(
padding: const EdgeInsets.only(right: 8),
child: ChoiceChip(
label: Text(option.name),
selected: selectedSlug == option.slug,
onSelected: (_) => onSelected(option.slug),
selectedColor: palette.brand,
labelStyle: TextStyle(
color: selectedSlug == option.slug
? Colors.white
: palette.ink,
fontWeight: selectedSlug == option.slug
? FontWeight.w700
: FontWeight.w500,
),
side: BorderSide.none,
backgroundColor: Colors.white,
shape: const StadiumBorder(),
showCheckmark: false,
),
),
],
),
);
}
}
