Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue #311: label data validation forms #319

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"next": "14.2.15",
"react": "^18",
"react-dom": "^18",
"react-hook-form": "^7.53.2",
"react-zoom-pan-pinch": "^3.6.1",
"swiper": "^11.1.14",
"ts-node": "^10.9.2",
Expand Down
269 changes: 91 additions & 178 deletions src/app/label-data-validation/page.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,79 @@
"use client";
import HorizontalNonLinearStepper, {
CustomStepperProps,
StepStatus,
} from "@/components/HorizontalNonLinearStepper";
import Dummy from "@/components/Dummy";
import ImageViewer from "@/components/ImageViewer";
import OrganizationForm from "@/components/OrganizationForm";
import {
HorizontalNonLinearStepper,
StepComponentProps,
StepperControls,
StepStatus,
} from "@/components/stepper";
import { LabelData, TEST_LABEL_DATA } from "@/types/organization";
import useBreakpoints from "@/utils/useBreakpoints";
import { Box, Button, Container, Typography } from "@mui/material";
import { Box, Button, Container } from "@mui/material";
import * as React from "react";
import { useState } from "react";

function LabelDataValidationPage() {
const [imageFiles, setImageFiles] = useState<File[]>([]);
const { isDownXs, isBetweenXsSm, isBetweenSmMd } = useBreakpoints();
const isMdOrBelow = isDownXs || isBetweenXsSm || isBetweenSmMd;
const [activeStep, setActiveStep] = React.useState(0);
const [stepStatuses, setStepStatuses] = React.useState<{
[k: number]: StepStatus;
}>({});
const { isDownXs, isBetweenXsSm, isBetweenSmMd, isBetweenMdLg } =
useBreakpoints();
const isLgOrBelow =
isDownXs || isBetweenXsSm || isBetweenSmMd || isBetweenMdLg;
const [activeStep, setActiveStep] = useState(0);
const [labelData, setLabelData] = useState<LabelData>(TEST_LABEL_DATA);
const [organizationStatus, setOrganizationStatus] = useState<StepStatus>(
StepStatus.Incomplete,
);
const [dummyStatus, setDummyStatus] = useState<StepStatus>(
StepStatus.Incomplete,
);

// To be removed, just for testing
const steps = ["Step 1", "Step 2", "Step 3", "Step 4"];
const createStep = (
Component: React.FC<StepComponentProps>,
props: StepComponentProps,
) => {
return {
title: props.title,
status: props.status,
setStatus: props.setStatus,
labelData: props.labelData,
setLabelData: props.setLabelData,
render: () => (
<Component
title={props.title}
status={props.status}
setStatus={props.setStatus}
labelData={props.labelData}
setLabelData={props.setLabelData}
/>
),
};
};

const steps = [
createStep(OrganizationForm, {
title: "Organizations",
status: organizationStatus,
setStatus: setOrganizationStatus,
labelData: labelData,
setLabelData: setLabelData,
}),
createStep(Dummy, {
title: "Dummy",
status: dummyStatus,
setStatus: setDummyStatus,
labelData: labelData,
setLabelData: setLabelData,
}),
];

const stepperProps = {
stepTitles: steps.map((step) => step.title),
stepStatuses: steps.map((step) => step.status),
activeStep,
setActiveStep,
};

const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.files) {
Expand All @@ -33,54 +87,51 @@ function LabelDataValidationPage() {

return (
<Container
className="flex flex-col h-screen max-w-[1920px]"
className="flex flex-col h-screen max-w-[1920px] max-h-[80vh]"
maxWidth={false}
data-testid="container"
>
{!isMdOrBelow && (
{!isLgOrBelow && (
<Box className="p-4 mt-4" data-testid="stepper">
<HorizontalNonLinearStepper
steps={steps}
activeStep={activeStep}
setActiveStep={setActiveStep}
stepStatuses={stepStatuses}
/>
stepTitles={stepperProps.stepTitles}
stepStatuses={stepperProps.stepStatuses}
activeStep={stepperProps.activeStep}
setActiveStep={stepperProps.setActiveStep}
/>
</Box>
)}

<Box className="flex flex-col md:flex-row" data-testid="main-content">
<Box className="flex flex-col lg:flex-row" data-testid="main-content">
<Box
className="flex w-full p-4 justify-center min-w-0 h-[720px]"
className="flex w-full py-4 justify-center min-w-0 h-[720px]"
data-testid="swiper-container"
>
<ImageViewer imageFiles={imageFiles} />
</Box>

{isMdOrBelow && (
<Box className="p-4 mt-4 border" data-testid="stepper-md">
{isLgOrBelow && (
<Box className="p-4 mt-4" data-testid="stepper-md">
<HorizontalNonLinearStepper
steps={steps}
activeStep={activeStep}
setActiveStep={setActiveStep}
stepStatuses={stepStatuses}
/>
stepTitles={stepperProps.stepTitles}
stepStatuses={stepperProps.stepStatuses}
activeStep={stepperProps.activeStep}
setActiveStep={stepperProps.setActiveStep}
/>
</Box>
)}

<Box
className="flex w-full p-4 justify-center min-w-0 min-h-[500px]"
className="flex w-full py-4 justify-center min-w-0 min-h-[500px] lg:max-h-[80vh] overflow-y-auto"
data-testid="form-container"
>
<Box
className="w-full h-[400px] p-4 text-center font-bold bg-gray-400"
data-testid="form-placeholder"
>
<StepControls
steps={steps}
activeStep={activeStep}
setActiveStep={setActiveStep}
stepStatuses={stepStatuses}
setStepStatuses={setStepStatuses}
<Box className="w-full text-center" data-testid="forms">
<Box className="">{steps[activeStep].render()}</Box>
<StepperControls
stepTitles={stepperProps.stepTitles}
stepStatuses={stepperProps.stepStatuses}
activeStep={stepperProps.activeStep}
setActiveStep={stepperProps.setActiveStep}
/>
</Box>
</Box>
Expand All @@ -103,142 +154,4 @@ function LabelDataValidationPage() {
);
}

// To be removed, just for testing
const StepControls: React.FC<CustomStepperProps> = ({
steps,
activeStep,
setActiveStep,
stepStatuses,
setStepStatuses,
}) => {
const stepsTotal = steps.length;
const allStepsCompleted = Object.values(stepStatuses).every(
(status) => status === StepStatus.Completed,
);

const handleNext = () => {
setActiveStep((prev) => Math.min(prev + 1, stepsTotal - 1));
};

const handleBack = () => {
setActiveStep((prev) => Math.max(prev - 1, 0));
};

const handleComplete = () => {
setStepStatuses?.((prev) => ({
...prev,
[activeStep]: StepStatus.Completed,
}));
};

const handleIncomplete = () => {
setStepStatuses?.((prev) => ({
...prev,
[activeStep]: StepStatus.Incomplete,
}));
};

const handleError = () => {
setStepStatuses?.((prev) => ({ ...prev, [activeStep]: StepStatus.Error }));
};

const handleReset = () => {
setActiveStep(0);
setStepStatuses?.({});
};

return (
<>
<Typography className="mt-2 mb-1 py-1">
{allStepsCompleted
? "All steps completed - you're finished"
: `Step ${activeStep + 1}`}
</Typography>

<Box className="flex justify-center gap-2 pt-2">
<Button
color="secondary"
disabled={activeStep === 0}
onClick={handleBack}
>
Back
</Button>
<Button
color="secondary"
onClick={handleNext}
disabled={activeStep >= stepsTotal - 1}
>
Next
</Button>
<Button
color="secondary"
onClick={handleComplete}
disabled={stepStatuses[activeStep] === StepStatus.Completed}
>
Complete Step
</Button>
<Button
color="secondary"
onClick={handleIncomplete}
disabled={stepStatuses[activeStep] === StepStatus.Incomplete}
>
Undo
</Button>
<Button
color="error"
onClick={handleError}
disabled={stepStatuses[activeStep] === StepStatus.Error}
>
Mark as Error
</Button>
<Button color="secondary" onClick={handleReset}>
Reset
</Button>
</Box>
</>
);
};

export default LabelDataValidationPage;







// function LabelDataValidationPage() {


// return (
// <Container
// className="flex flex-col h-screen max-w-[1920px] overflow-hidden"
// maxWidth={false}
// >
// <Box className="p-4 mt-4">
// <HorizontalNonLinearStepper
// steps={steps}
// activeStep={activeStep}
// setActiveStep={setActiveStep}
// stepStatuses={stepStatuses}
// />
// </Box>

// <Box className="flex flex-1 overflow-hidden flex-col md:flex-row">
// <Box className="flex-1 p-4 flex justify-center">
// {/* Carousel Placeholder: To be removed, just for testing */}
// <Box className="w-full h-3/4 p-4 text-center font-bold bg-gray-300">
// Carousel Placeholder
// </Box>
// </Box>

// <Box className="flex flex-1 p-4 justify-center overflow-y-auto">
// {/* Form Placeholder: To be removed, just for testing */}
// <Box className="w-full h-3/4 p-4 text-center font-bold bg-gray-400">
// <StepControls
// steps={steps}
// activeStep={activeStep}
// setActiveStep={setActiveStep}
// stepStatuses={stepStatuses}
// setStepStatuses={setStepStatuses}
// />
16 changes: 0 additions & 16 deletions src/app/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ const theme = createTheme({
background: {
default: "#C5C5C5", // Light Grey
},
text: {
primary: colors.common.black,
secondary: colors.common.white,
},
},
typography: {
fontFamily: "Roboto, Arial, sans-serif",
Expand Down Expand Up @@ -86,18 +82,6 @@ const theme = createTheme({
},
},
},
MuiInputBase: {
styleOverrides: {
root: {
backgroundColor: colors.common.white,
border: "3px solid #BEBCBC", // Stroke color
color: colors.common.black,
"&::placeholder": {
color: "#BCBABA", // Placeholder color
},
},
},
},
MuiAppBar: {
styleOverrides: {
root: {
Expand Down
7 changes: 7 additions & 0 deletions src/components/Dummy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { StepComponentProps } from "./stepper";

function Dummy({ title }: StepComponentProps) {
return <div>{title}</div>;
}

export default Dummy;
Loading
Loading