add print buttons to mobile
This commit is contained in:
parent
95a3a08492
commit
dec4b848b6
@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Vite + React + TS</title>
|
<title>Task Receipts</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
@ -89,6 +89,7 @@ export function App() {
|
|||||||
onTaskSelect={setSelectedTask}
|
onTaskSelect={setSelectedTask}
|
||||||
onStepSelect={setSelectedStep}
|
onStepSelect={setSelectedStep}
|
||||||
onBack={handleBack}
|
onBack={handleBack}
|
||||||
|
onPrintTask={handlePrintTask}
|
||||||
onPrintStep={handlePrintStep}
|
onPrintStep={handlePrintStep}
|
||||||
onAddNote={handleAddNote}
|
onAddNote={handleAddNote}
|
||||||
/>
|
/>
|
||||||
|
@ -125,7 +125,7 @@ export function DesktopLayout({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box onClick={() => onStepSelect(step)} sx={{ flex: 1 }}>
|
<Box onClick={() => onStepSelect(step)} sx={{ flex: 1 }}>
|
||||||
<Typography>{step.name}</Typography>
|
<Typography>{step.order}: {step.name}</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
{onPrintStep && selectedUser && (
|
{onPrintStep && selectedUser && (
|
||||||
<IconButton
|
<IconButton
|
||||||
|
@ -3,6 +3,7 @@ import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
|||||||
import PrintIcon from '@mui/icons-material/Print';
|
import PrintIcon from '@mui/icons-material/Print';
|
||||||
import type { GroupWithTasks, TaskWithSteps, StepWithNotes } from '../types';
|
import type { GroupWithTasks, TaskWithSteps, StepWithNotes } from '../types';
|
||||||
import { CreateButtons } from '../components/CreateButtons';
|
import { CreateButtons } from '../components/CreateButtons';
|
||||||
|
import { useUserSelection } from '../hooks/useUserSelection';
|
||||||
|
|
||||||
function isGroupView(selectedGroup?: GroupWithTasks) {
|
function isGroupView(selectedGroup?: GroupWithTasks) {
|
||||||
return !selectedGroup;
|
return !selectedGroup;
|
||||||
@ -16,6 +17,10 @@ function isStepView(selectedTask?: TaskWithSteps, selectedStep?: StepWithNotes)
|
|||||||
return selectedTask && !selectedStep;
|
return selectedTask && !selectedStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isGroupWithTasks(group: any): group is GroupWithTasks {
|
||||||
|
return group && typeof group.id === 'string' && Array.isArray(group.tasks);
|
||||||
|
}
|
||||||
|
|
||||||
export function MobileLayout({
|
export function MobileLayout({
|
||||||
groups = [],
|
groups = [],
|
||||||
selectedGroup,
|
selectedGroup,
|
||||||
@ -25,6 +30,7 @@ export function MobileLayout({
|
|||||||
onTaskSelect,
|
onTaskSelect,
|
||||||
onStepSelect,
|
onStepSelect,
|
||||||
onBack,
|
onBack,
|
||||||
|
onPrintTask,
|
||||||
onPrintStep,
|
onPrintStep,
|
||||||
onAddNote
|
onAddNote
|
||||||
}: {
|
}: {
|
||||||
@ -36,9 +42,11 @@ export function MobileLayout({
|
|||||||
onTaskSelect: (task: TaskWithSteps | undefined) => void;
|
onTaskSelect: (task: TaskWithSteps | undefined) => void;
|
||||||
onStepSelect: (step: StepWithNotes | undefined) => void;
|
onStepSelect: (step: StepWithNotes | undefined) => void;
|
||||||
onBack: () => void;
|
onBack: () => void;
|
||||||
|
onPrintTask?: (taskId: string, userId: string) => void;
|
||||||
onPrintStep?: (stepId: string, userId: string) => void;
|
onPrintStep?: (stepId: string, userId: string) => void;
|
||||||
onAddNote?: (content: string) => void;
|
onAddNote?: (content: string) => void;
|
||||||
}) {
|
}) {
|
||||||
|
const { selectedUser } = useUserSelection();
|
||||||
const groupList: GroupWithTasks[] = groups;
|
const groupList: GroupWithTasks[] = groups;
|
||||||
const taskList: TaskWithSteps[] = (selectedGroup?.tasks as TaskWithSteps[]) ?? [];
|
const taskList: TaskWithSteps[] = (selectedGroup?.tasks as TaskWithSteps[]) ?? [];
|
||||||
const stepList: StepWithNotes[] = (selectedTask?.steps as StepWithNotes[]) ?? [];
|
const stepList: StepWithNotes[] = (selectedTask?.steps as StepWithNotes[]) ?? [];
|
||||||
@ -61,6 +69,14 @@ export function MobileLayout({
|
|||||||
<ArrowBackIcon />
|
<ArrowBackIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<Typography variant="h6">{selectedTask.name}</Typography>
|
<Typography variant="h6">{selectedTask.name}</Typography>
|
||||||
|
{onPrintTask && selectedUser && (
|
||||||
|
<IconButton
|
||||||
|
onClick={() => onPrintTask(String(selectedTask.id), String(selectedUser.id))}
|
||||||
|
sx={{ ml: 'auto' }}
|
||||||
|
>
|
||||||
|
<PrintIcon />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -70,9 +86,9 @@ export function MobileLayout({
|
|||||||
<ArrowBackIcon />
|
<ArrowBackIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<Typography variant="h6">{selectedStep.name}</Typography>
|
<Typography variant="h6">{selectedStep.name}</Typography>
|
||||||
{onPrintStep && (
|
{onPrintStep && selectedUser && (
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => onPrintStep(String(selectedStep.id), '1')} // TODO: Get real user ID
|
onClick={() => onPrintStep(String(selectedStep.id), String(selectedUser.id))}
|
||||||
sx={{ ml: 'auto' }}
|
sx={{ ml: 'auto' }}
|
||||||
>
|
>
|
||||||
<PrintIcon />
|
<PrintIcon />
|
||||||
@ -97,7 +113,7 @@ export function MobileLayout({
|
|||||||
sx={{
|
sx={{
|
||||||
p: 2,
|
p: 2,
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
bgcolor: selectedGroup?.id === group.id ? 'action.selected' : 'transparent',
|
// no bg color
|
||||||
'&:hover': { bgcolor: 'action.hover' },
|
'&:hover': { bgcolor: 'action.hover' },
|
||||||
}}
|
}}
|
||||||
onClick={() => onGroupSelect(group)}
|
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 }}>
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
||||||
<Typography variant="h6">Tasks</Typography>
|
<Typography variant="h6">Tasks</Typography>
|
||||||
@ -121,11 +137,27 @@ export function MobileLayout({
|
|||||||
sx={{
|
sx={{
|
||||||
p: 2,
|
p: 2,
|
||||||
cursor: 'pointer',
|
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)}
|
|
||||||
>
|
>
|
||||||
<Typography>{task.name}</Typography>
|
<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>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
@ -146,10 +178,25 @@ export function MobileLayout({
|
|||||||
p: 2,
|
p: 2,
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
bgcolor: selectedStep?.id === step.id ? 'action.selected' : 'transparent',
|
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>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -24,10 +24,11 @@ export const formatUtils = {
|
|||||||
* @param startIndex Starting index for numbering (0 for no numbers)
|
* @param startIndex Starting index for numbering (0 for no numbers)
|
||||||
* @returns Array of formatted lines
|
* @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) => {
|
return items.map((item, index) => {
|
||||||
const num = startIndex > 0 ? `${index + startIndex}: ` : '';
|
const num = startIndex > 0 ? `${index + startIndex}: ` : '';
|
||||||
return this.formatCheckbox(`${num}${item}`);
|
const body = this.formatCheckbox(`${num}${item}`);
|
||||||
|
return `${prefix}${body}`;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -37,15 +37,10 @@ export class TestPrinter implements Printer {
|
|||||||
|
|
||||||
const content = [
|
const content = [
|
||||||
...formatUtils.formatSection(`Task: ${task.name}`, ''),
|
...formatUtils.formatSection(`Task: ${task.name}`, ''),
|
||||||
...taskSteps.map((step, index) =>
|
...formatUtils.formatList(taskSteps.map((step, index) =>
|
||||||
formatUtils.formatSection(
|
formatUtils.formatStepHeader(step.name, index + 1, task.name, true)
|
||||||
formatUtils.formatStepHeader(step.name, index + 1, task.name, true),
|
), 0, '- '),
|
||||||
step.instructions,
|
].join('\n') + '\n';
|
||||||
'-',
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
).flat(),
|
|
||||||
].join('\n');
|
|
||||||
|
|
||||||
await fs.writeFile(filename, content);
|
await fs.writeFile(filename, content);
|
||||||
logger.info(`Printed task ${task.id} to ${filename}`);
|
logger.info(`Printed task ${task.id} to ${filename}`);
|
||||||
@ -69,7 +64,7 @@ export class TestPrinter implements Printer {
|
|||||||
const content = formatUtils.formatSection(
|
const content = formatUtils.formatSection(
|
||||||
formatUtils.formatStepHeader(step.name, stepNumber, task?.name),
|
formatUtils.formatStepHeader(step.name, stepNumber, task?.name),
|
||||||
step.instructions
|
step.instructions
|
||||||
).join('\n');
|
).join('\n') + '\n';
|
||||||
|
|
||||||
await fs.writeFile(filename, content);
|
await fs.writeFile(filename, content);
|
||||||
logger.info(`Printed step ${step.id} to ${filename}`);
|
logger.info(`Printed step ${step.id} to ${filename}`);
|
||||||
|
Loading…
Reference in New Issue
Block a user