mirror of
https://github.com/s-frick/effigenix.git
synced 2026-03-28 10:39:35 +01:00
feat(frontend): TUI-Screens für Rezept-Filter, Archivierung und Chargen-Einbuchung
Production: Rezeptliste mit Status-Filter (Draft/Active/Archived), Rezept archivieren für aktive Rezepte, list() gibt RecipeSummaryDTO zurück. Inventory: Charge einbuchen (AddBatch) mit neuem Stocks-Resource und Screens.
This commit is contained in:
parent
f2003a3093
commit
ec736cf294
16 changed files with 553 additions and 16 deletions
|
|
@ -9,8 +9,8 @@ import { SuccessDisplay } from '../shared/SuccessDisplay.js';
|
|||
import { ConfirmDialog } from '../shared/ConfirmDialog.js';
|
||||
import { client } from '../../utils/api-client.js';
|
||||
|
||||
type MenuAction = 'add-ingredient' | 'remove-ingredient' | 'add-step' | 'remove-step' | 'activate' | 'back';
|
||||
type Mode = 'menu' | 'select-step-to-remove' | 'confirm-remove' | 'select-ingredient-to-remove' | 'confirm-remove-ingredient' | 'confirm-activate';
|
||||
type MenuAction = 'add-ingredient' | 'remove-ingredient' | 'add-step' | 'remove-step' | 'activate' | 'archive' | 'back';
|
||||
type Mode = 'menu' | 'select-step-to-remove' | 'confirm-remove' | 'select-ingredient-to-remove' | 'confirm-remove-ingredient' | 'confirm-activate' | 'confirm-archive';
|
||||
|
||||
function errorMessage(err: unknown): string {
|
||||
return err instanceof Error ? err.message : 'Unbekannter Fehler';
|
||||
|
|
@ -33,6 +33,7 @@ export function RecipeDetailScreen() {
|
|||
const [ingredientToRemove, setIngredientToRemove] = useState<IngredientDTO | null>(null);
|
||||
|
||||
const isDraft = recipe?.status === 'DRAFT';
|
||||
const isActive = recipe?.status === 'ACTIVE';
|
||||
|
||||
const menuItems: { id: MenuAction; label: string }[] = [
|
||||
...(isDraft ? [
|
||||
|
|
@ -42,6 +43,9 @@ export function RecipeDetailScreen() {
|
|||
{ id: 'remove-step' as const, label: '[Schritt entfernen]' },
|
||||
{ id: 'activate' as const, label: '[Rezept aktivieren]' },
|
||||
] : []),
|
||||
...(isActive ? [
|
||||
{ id: 'archive' as const, label: '[Rezept archivieren]' },
|
||||
] : []),
|
||||
{ id: 'back' as const, label: '[Zurück]' },
|
||||
];
|
||||
|
||||
|
|
@ -127,6 +131,9 @@ export function RecipeDetailScreen() {
|
|||
case 'activate':
|
||||
setMode('confirm-activate');
|
||||
break;
|
||||
case 'archive':
|
||||
setMode('confirm-archive');
|
||||
break;
|
||||
case 'back':
|
||||
back();
|
||||
break;
|
||||
|
|
@ -179,6 +186,20 @@ export function RecipeDetailScreen() {
|
|||
setActionLoading(false);
|
||||
}, [recipe]);
|
||||
|
||||
const handleArchive = useCallback(async () => {
|
||||
if (!recipe) return;
|
||||
setMode('menu');
|
||||
setActionLoading(true);
|
||||
try {
|
||||
const updated = await client.recipes.archiveRecipe(recipe.id);
|
||||
setRecipe(updated);
|
||||
setSuccessMessage('Rezept wurde archiviert.');
|
||||
} catch (err: unknown) {
|
||||
setError(errorMessage(err));
|
||||
}
|
||||
setActionLoading(false);
|
||||
}, [recipe]);
|
||||
|
||||
if (loading) return <LoadingSpinner label="Lade Rezept..." />;
|
||||
if (error && !recipe) return <ErrorDisplay message={error} onDismiss={back} />;
|
||||
if (!recipe) return <Text color="red">Rezept nicht gefunden.</Text>;
|
||||
|
|
@ -307,6 +328,14 @@ export function RecipeDetailScreen() {
|
|||
/>
|
||||
)}
|
||||
|
||||
{mode === 'confirm-archive' && (
|
||||
<ConfirmDialog
|
||||
message="Rezept wirklich archivieren? Der Status wechselt zu ARCHIVED."
|
||||
onConfirm={() => void handleArchive()}
|
||||
onCancel={() => setMode('menu')}
|
||||
/>
|
||||
)}
|
||||
|
||||
{mode === 'menu' && (
|
||||
<Box flexDirection="column">
|
||||
<Text color="gray" bold>Aktionen:</Text>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue