add print buttons to mobile

This commit is contained in:
Sean Sube 2025-06-14 23:09:12 -05:00
parent 95a3a08492
commit dec4b848b6
No known key found for this signature in database
GPG Key ID: 3EED7B957D362AF1
6 changed files with 70 additions and 26 deletions

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>Task Receipts</title>
</head>
<body>
<div id="root"></div>

View File

@ -89,6 +89,7 @@ export function App() {
onTaskSelect={setSelectedTask}
onStepSelect={setSelectedStep}
onBack={handleBack}
onPrintTask={handlePrintTask}
onPrintStep={handlePrintStep}
onAddNote={handleAddNote}
/>

View File

@ -125,7 +125,7 @@ export function DesktopLayout({
}}
>
<Box onClick={() => onStepSelect(step)} sx={{ flex: 1 }}>
<Typography>{step.name}</Typography>
<Typography>{step.order}: {step.name}</Typography>
</Box>
{onPrintStep && selectedUser && (
<IconButton

View File

@ -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({
<ArrowBackIcon />
</IconButton>
<Typography variant="h6">{selectedTask.name}</Typography>
{onPrintTask && selectedUser && (
<IconButton
onClick={() => onPrintTask(String(selectedTask.id), String(selectedUser.id))}
sx={{ ml: 'auto' }}
>
<PrintIcon />
</IconButton>
)}
</Box>
)}
@ -70,9 +86,9 @@ export function MobileLayout({
<ArrowBackIcon />
</IconButton>
<Typography variant="h6">{selectedStep.name}</Typography>
{onPrintStep && (
{onPrintStep && selectedUser && (
<IconButton
onClick={() => onPrintStep(String(selectedStep.id), '1')} // TODO: Get real user ID
onClick={() => onPrintStep(String(selectedStep.id), String(selectedUser.id))}
sx={{ ml: 'auto' }}
>
<PrintIcon />
@ -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) && (
<>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
<Typography variant="h6">Tasks</Typography>
@ -121,12 +137,28 @@ 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)}
>
<Box onClick={() => onTaskSelect(task)} sx={{ flex: 1 }}>
<Typography>{task.name}</Typography>
</Box>
{onPrintTask && selectedUser && (
<IconButton
size="small"
onClick={(e) => {
e.stopPropagation();
onPrintTask(String(task.id), String(selectedUser.id));
}}
>
<PrintIcon />
</IconButton>
)}
</Box>
))}
</Box>
</>
@ -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)}
>
<Typography>{step.name}</Typography>
<Box onClick={() => onStepSelect(step)} sx={{ flex: 1 }}>
<Typography>{step.order}: {step.name}</Typography>
</Box>
{onPrintStep && selectedUser && (
<IconButton
size="small"
onClick={(e) => {
e.stopPropagation();
onPrintStep(String(step.id), String(selectedUser.id));
}}
>
<PrintIcon />
</IconButton>
)}
</Box>
))}
</Box>

View File

@ -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}`;
});
},

View File

@ -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}`);