1
0
Fork 0
mirror of https://github.com/s-frick/effigenix.git synced 2026-03-28 12:19:35 +01:00

feat(tui): neue Backend-Features anbinden und Status-Werte korrigieren

TUI-Anbindung für Reservierung bestätigen (US-4.3), Produktionsauftrag
umterminieren und filtern (US-P17). Status-Werte CREATED→PLANNED und
IN_PRODUCTION→IN_PROGRESS korrigiert. Fehlenden GET /{id} Endpoint für
Produktionsaufträge im Backend ergänzt.
This commit is contained in:
Sebastian Frick 2026-02-25 23:36:42 +01:00
parent 8a84bf5f25
commit 417f8fcdae
14 changed files with 467 additions and 27 deletions

View file

@ -10,24 +10,25 @@ import { PRODUCTION_ORDER_STATUS_LABELS, PRIORITY_LABELS } from '@effigenix/api-
import type { ProductionOrderStatus, Priority } from '@effigenix/api-client';
const STATUS_COLORS: Record<string, string> = {
CREATED: 'gray',
PLANNED: 'gray',
RELEASED: 'yellow',
IN_PRODUCTION: 'blue',
IN_PROGRESS: 'blue',
COMPLETED: 'green',
CANCELLED: 'red',
};
type Mode = 'view' | 'menu' | 'start-batch-input';
type Mode = 'view' | 'menu' | 'start-batch-input' | 'reschedule-input';
export function ProductionOrderDetailScreen() {
const { params, back } = useNavigation();
const {
productionOrder, loading, error,
fetchProductionOrder, releaseProductionOrder, startProductionOrder, clearError,
fetchProductionOrder, releaseProductionOrder, rescheduleProductionOrder, startProductionOrder, clearError,
} = useProductionOrders();
const [mode, setMode] = useState<Mode>('view');
const [menuIndex, setMenuIndex] = useState(0);
const [batchId, setBatchId] = useState('');
const [newDate, setNewDate] = useState('');
const [success, setSuccess] = useState<string | null>(null);
const orderId = params.orderId ?? '';
@ -39,11 +40,13 @@ export function ProductionOrderDetailScreen() {
const getMenuItems = () => {
const items: { label: string; action: string }[] = [];
const status = productionOrder?.status;
if (status === 'CREATED') {
if (status === 'PLANNED') {
items.push({ label: 'Freigeben', action: 'release' });
items.push({ label: 'Umterminieren', action: 'reschedule' });
}
if (status === 'RELEASED') {
items.push({ label: 'Produktion starten', action: 'start' });
items.push({ label: 'Umterminieren', action: 'reschedule' });
}
return items;
};
@ -68,9 +71,24 @@ export function ProductionOrderDetailScreen() {
}
};
const handleReschedule = async () => {
if (!newDate.trim()) return;
const result = await rescheduleProductionOrder(orderId, newDate.trim());
if (result) {
setSuccess(`Umterminiert auf ${newDate.trim()}.`);
setMode('view');
setNewDate('');
}
};
useInput((_input, key) => {
if (loading) return;
if (mode === 'reschedule-input') {
if (key.escape) setMode('menu');
return;
}
if (mode === 'start-batch-input') {
if (key.escape) setMode('menu');
return;
@ -82,6 +100,10 @@ export function ProductionOrderDetailScreen() {
if (key.return && menuItems[menuIndex]) {
const action = menuItems[menuIndex].action;
if (action === 'release') void handleRelease();
if (action === 'reschedule') {
setMode('reschedule-input');
setNewDate('');
}
if (action === 'start') {
setMode('start-batch-input');
setBatchId('');
@ -175,6 +197,22 @@ export function ProductionOrderDetailScreen() {
</Box>
)}
{mode === 'reschedule-input' && (
<Box flexDirection="column" borderStyle="round" borderColor="yellow" paddingX={1}>
<Text color="yellow" bold>Neues Datum (YYYY-MM-DD):</Text>
<Box>
<Text color="gray"> </Text>
<TextInput
value={newDate}
onChange={setNewDate}
onSubmit={() => void handleReschedule()}
focus={true}
/>
</Box>
<Text color="gray" dimColor>Enter bestätigen · Escape abbrechen</Text>
</Box>
)}
<Box marginTop={1}>
<Text color="gray" dimColor>
{menuItems.length > 0 ? '[m] Aktionsmenü · ' : ''}Backspace Zurück