From dec4b848b6a5cdbcc18ef7cf1dab826428596c93 Mon Sep 17 00:00:00 2001 From: Sean Sube Date: Sat, 14 Jun 2025 23:09:12 -0500 Subject: [PATCH] add print buttons to mobile --- client/index.html | 2 +- client/src/App.tsx | 1 + client/src/layouts/DesktopLayout.tsx | 4 +- client/src/layouts/MobileLayout.tsx | 67 +++++++++++++++++++++++----- server/src/printer/format-utils.ts | 5 ++- server/src/printer/test-printer.ts | 17 +++---- 6 files changed, 70 insertions(+), 26 deletions(-) diff --git a/client/index.html b/client/index.html index e4b78ea..9603ad9 100644 --- a/client/index.html +++ b/client/index.html @@ -4,7 +4,7 @@ - Vite + React + TS + Task Receipts
diff --git a/client/src/App.tsx b/client/src/App.tsx index 1a63a45..c341bac 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -89,6 +89,7 @@ export function App() { onTaskSelect={setSelectedTask} onStepSelect={setSelectedStep} onBack={handleBack} + onPrintTask={handlePrintTask} onPrintStep={handlePrintStep} onAddNote={handleAddNote} /> diff --git a/client/src/layouts/DesktopLayout.tsx b/client/src/layouts/DesktopLayout.tsx index 7c45da0..4556f3a 100644 --- a/client/src/layouts/DesktopLayout.tsx +++ b/client/src/layouts/DesktopLayout.tsx @@ -125,7 +125,7 @@ export function DesktopLayout({ }} > onStepSelect(step)} sx={{ flex: 1 }}> - {step.name} + {step.order}: {step.name} {onPrintStep && selectedUser && ( ); -} \ No newline at end of file +} diff --git a/client/src/layouts/MobileLayout.tsx b/client/src/layouts/MobileLayout.tsx index 360c814..c540481 100644 --- a/client/src/layouts/MobileLayout.tsx +++ b/client/src/layouts/MobileLayout.tsx @@ -3,6 +3,7 @@ import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import PrintIcon from '@mui/icons-material/Print'; import type { GroupWithTasks, TaskWithSteps, StepWithNotes } from '../types'; import { CreateButtons } from '../components/CreateButtons'; +import { useUserSelection } from '../hooks/useUserSelection'; function isGroupView(selectedGroup?: GroupWithTasks) { return !selectedGroup; @@ -16,6 +17,10 @@ function isStepView(selectedTask?: TaskWithSteps, selectedStep?: StepWithNotes) return selectedTask && !selectedStep; } +function isGroupWithTasks(group: any): group is GroupWithTasks { + return group && typeof group.id === 'string' && Array.isArray(group.tasks); +} + export function MobileLayout({ groups = [], selectedGroup, @@ -25,6 +30,7 @@ export function MobileLayout({ onTaskSelect, onStepSelect, onBack, + onPrintTask, onPrintStep, onAddNote }: { @@ -36,9 +42,11 @@ export function MobileLayout({ onTaskSelect: (task: TaskWithSteps | undefined) => void; onStepSelect: (step: StepWithNotes | undefined) => void; onBack: () => void; + onPrintTask?: (taskId: string, userId: string) => void; onPrintStep?: (stepId: string, userId: string) => void; onAddNote?: (content: string) => void; }) { + const { selectedUser } = useUserSelection(); const groupList: GroupWithTasks[] = groups; const taskList: TaskWithSteps[] = (selectedGroup?.tasks as TaskWithSteps[]) ?? []; const stepList: StepWithNotes[] = (selectedTask?.steps as StepWithNotes[]) ?? []; @@ -61,6 +69,14 @@ export function MobileLayout({ {selectedTask.name} + {onPrintTask && selectedUser && ( + onPrintTask(String(selectedTask.id), String(selectedUser.id))} + sx={{ ml: 'auto' }} + > + + + )} )} @@ -70,9 +86,9 @@ export function MobileLayout({ {selectedStep.name} - {onPrintStep && ( + {onPrintStep && selectedUser && ( onPrintStep(String(selectedStep.id), '1')} // TODO: Get real user ID + onClick={() => onPrintStep(String(selectedStep.id), String(selectedUser.id))} sx={{ ml: 'auto' }} > @@ -97,7 +113,7 @@ export function MobileLayout({ sx={{ p: 2, cursor: 'pointer', - bgcolor: selectedGroup?.id === group.id ? 'action.selected' : 'transparent', + // no bg color '&:hover': { bgcolor: 'action.hover' }, }} onClick={() => onGroupSelect(group)} @@ -108,7 +124,7 @@ export function MobileLayout({ )} - {isTaskView(selectedGroup, selectedTask) && ( + {isTaskView(selectedGroup, selectedTask) && isGroupWithTasks(selectedGroup) && ( <> Tasks @@ -121,11 +137,27 @@ export function MobileLayout({ sx={{ p: 2, cursor: 'pointer', - bgcolor: selectedTask?.id === task.id ? 'action.selected' : 'transparent', + // no bg color + '&:hover': { bgcolor: 'action.hover' }, + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', }} - onClick={() => onTaskSelect(task)} > - {task.name} + onTaskSelect(task)} sx={{ flex: 1 }}> + {task.name} + + {onPrintTask && selectedUser && ( + { + e.stopPropagation(); + onPrintTask(String(task.id), String(selectedUser.id)); + }} + > + + + )} ))} @@ -146,10 +178,25 @@ export function MobileLayout({ p: 2, cursor: 'pointer', bgcolor: selectedStep?.id === step.id ? 'action.selected' : 'transparent', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', }} - onClick={() => onStepSelect(step)} > - {step.name} + onStepSelect(step)} sx={{ flex: 1 }}> + {step.order}: {step.name} + + {onPrintStep && selectedUser && ( + { + e.stopPropagation(); + onPrintStep(String(step.id), String(selectedUser.id)); + }} + > + + + )} ))} @@ -191,4 +238,4 @@ export function MobileLayout({ ); -} \ No newline at end of file +} diff --git a/server/src/printer/format-utils.ts b/server/src/printer/format-utils.ts index c57c590..28f9f6f 100644 --- a/server/src/printer/format-utils.ts +++ b/server/src/printer/format-utils.ts @@ -24,10 +24,11 @@ export const formatUtils = { * @param startIndex Starting index for numbering (0 for no numbers) * @returns Array of formatted lines */ - formatList(items: string[], startIndex: number = 0): string[] { + formatList(items: string[], startIndex: number = 0, prefix: string = ''): string[] { return items.map((item, index) => { const num = startIndex > 0 ? `${index + startIndex}: ` : ''; - return this.formatCheckbox(`${num}${item}`); + const body = this.formatCheckbox(`${num}${item}`); + return `${prefix}${body}`; }); }, diff --git a/server/src/printer/test-printer.ts b/server/src/printer/test-printer.ts index 118b358..7786f51 100644 --- a/server/src/printer/test-printer.ts +++ b/server/src/printer/test-printer.ts @@ -37,15 +37,10 @@ export class TestPrinter implements Printer { const content = [ ...formatUtils.formatSection(`Task: ${task.name}`, ''), - ...taskSteps.map((step, index) => - formatUtils.formatSection( - formatUtils.formatStepHeader(step.name, index + 1, task.name, true), - step.instructions, - '-', - true, - ) - ).flat(), - ].join('\n'); + ...formatUtils.formatList(taskSteps.map((step, index) => + formatUtils.formatStepHeader(step.name, index + 1, task.name, true) + ), 0, '- '), + ].join('\n') + '\n'; await fs.writeFile(filename, content); logger.info(`Printed task ${task.id} to ${filename}`); @@ -69,7 +64,7 @@ export class TestPrinter implements Printer { const content = formatUtils.formatSection( formatUtils.formatStepHeader(step.name, stepNumber, task?.name), step.instructions - ).join('\n'); + ).join('\n') + '\n'; await fs.writeFile(filename, content); logger.info(`Printed step ${step.id} to ${filename}`); @@ -80,4 +75,4 @@ export class TestPrinter implements Printer { printed_at: new Date(), }); } -} \ No newline at end of file +}