Skip to content

Commit

Permalink
issue #234: ui changes
Browse files Browse the repository at this point in the history
  • Loading branch information
k-allagbe committed Feb 10, 2025
1 parent 5cfffbc commit 42c8bf6
Show file tree
Hide file tree
Showing 14 changed files with 452 additions and 279 deletions.
15 changes: 7 additions & 8 deletions src/components/BaseInformationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { useEffect } from "react";
import { FormProvider, useForm, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { VerifiedInput } from "./VerifiedFieldComponents";
import VerifiedQuantityMultiInput from "./VerifiedQuantityMultiInput";
import VerifiedQuantityList from "./VerifiedQuantityList";
import VerifiedRegistrationList from "./VerifiedRegistrationList";

const BaseInformationForm: React.FC<FormComponentProps> = ({
loading = false,
Expand Down Expand Up @@ -46,13 +47,11 @@ const BaseInformationForm: React.FC<FormComponentProps> = ({
path="baseInformation.name"
loading={loading}
/>
<VerifiedInput
<VerifiedRegistrationList
label={t("baseInformation.fields.registrationNumber.label")}
placeholder={t(
"baseInformation.fields.registrationNumber.placeholder",
)}
path="baseInformation.registrationNumber"
loading={loading}
registrationTypes={["Fertilizer", "Ingredient"]}
/>
<VerifiedInput
label={t("baseInformation.fields.lotNumber.label")}
Expand All @@ -66,19 +65,19 @@ const BaseInformationForm: React.FC<FormComponentProps> = ({
path="baseInformation.npk"
loading={loading}
/>
<VerifiedQuantityMultiInput
<VerifiedQuantityList
label={t("baseInformation.fields.weight.label")}
path="baseInformation.weight"
unitOptions={UNITS.weight}
loading={loading}
/>
<VerifiedQuantityMultiInput
<VerifiedQuantityList
label={t("baseInformation.fields.density.label")}
path="baseInformation.density"
unitOptions={UNITS.density}
loading={loading}
/>
<VerifiedQuantityMultiInput
<VerifiedQuantityList
label={t("baseInformation.fields.volume.label")}
path="baseInformation.volume"
unitOptions={UNITS.volume}
Expand Down
10 changes: 5 additions & 5 deletions src/components/QuantityInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface QuantityInputProps {
disabled?: boolean;
unitRules?: RegisterOptions;
onFocus?: () => void;
onblur?: () => void;
onBlur?: () => void;
verified?: boolean;
}

Expand All @@ -22,7 +22,7 @@ const QuantityInput = ({
disabled = false,
unitRules,
onFocus,
onblur,
onBlur,
verified,
}: QuantityInputProps) => {
const { t } = useTranslation("labelDataValidator");
Expand Down Expand Up @@ -50,7 +50,7 @@ const QuantityInput = ({
disabled={disabled}
onFocus={onFocus}
onBlur={(e) => {
onblur?.();
onBlur?.();
field.onChange(e.target.value.trim());
}}
aria-label={t("quantityInput.accessibility.value")}
Expand Down Expand Up @@ -81,13 +81,13 @@ const QuantityInput = ({
renderInput={(params) => (
<StyledTextField
{...params}
className={`!w-[10ch] !px-2 bg-gray-100 ${verified ? "bg-gray-300": ""}`}
className={`!w-[10ch] !px-2 bg-gray-100 ${verified ? "bg-gray-300" : ""}`}
aria-label={t("quantityInput.accessibility.unit")}
data-testid={`${name}-unit-input`}
placeholder={t("quantityInput.placeholder.unit")}
onFocus={onFocus}
onBlur={(e) => {
onblur?.();
onBlur?.();
field.onChange(e.target.value.trim());
}}
error={!!error}
Expand Down
88 changes: 88 additions & 0 deletions src/components/RegistrationInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { RegistrationType } from "@/types/types";
import { Box, MenuItem, Select } from "@mui/material";
import { Control, Controller, RegisterOptions } from "react-hook-form";
import { useTranslation } from "react-i18next";
import StyledTextField from "./StyledTextField";

interface RegistrationInputProps {
name: string;
control: Control;
disabled?: boolean;
typeRules?: RegisterOptions;
onFocus?: () => void;
onBlur?: () => void;
verified?: boolean;
}

const RegistrationInput = ({
name,
control,
disabled = false,
typeRules,
onFocus,
onBlur,
verified,
}: RegistrationInputProps) => {
const { t } = useTranslation("labelDataValidator");

return (
<Box className="flex w-full" data-testid={`${name}-container`}>
{/* Identifier Input Field */}
<Controller
name={`${name}.identifier`}
control={control}
rules={{
pattern: {
value: /^\d{7}[A-Z]$/,
message: "errors.invalidRegistrationNumber",
},
}}
render={({ field, fieldState: { error } }) => (
<StyledTextField
{...field}
placeholder={t("baseInformation.fields.reg.placeholder")}
disabled={disabled}
onFocus={onFocus}
onBlur={(e) => {
onBlur?.();
field.onChange(e.target.value.trim());
}}
aria-label={t("baseInformation.fields.reg.accessibility")}
data-testid={`${name}-number-input`}
error={!!error}
helperText={error?.message ? t(error.message) : ""}
/>
)}
/>

{/* Registration Type Selection Field */}
<Controller
name={`${name}.type`}
control={control}
rules={typeRules}
render={({ field, fieldState: { error } }) => (
<Select
{...field}
className={`!w-[20ch] !text-[15px] ${verified ? "bg-inherit" : "bg-gray-100"} px-2`}
variant="standard"
autoComplete="off"
value={field.value || ""}
onChange={(event) => field.onChange(event.target.value)}
disabled={disabled}
fullWidth
disableUnderline
>
<MenuItem value={RegistrationType.FERTILIZER}>
{t("baseInformation.fields.reg.type.fertilizer")}
</MenuItem>
<MenuItem value={RegistrationType.INGREDIENT}>
{t("baseInformation.fields.reg.type.ingredient")}
</MenuItem>
</Select>
)}
/>
</Box>
);
};

export default RegistrationInput;
36 changes: 36 additions & 0 deletions src/components/StyledDeleteButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import DeleteIcon from "@mui/icons-material/Delete";
import { IconButton, IconButtonProps, Tooltip } from "@mui/material";
import React from "react";

interface StyledDeleteButtonProps extends IconButtonProps {
tooltip: string;
tooltipDelay?: number;
hideButton?: boolean;
}

const StyledDeleteButton = React.forwardRef<
HTMLButtonElement,
StyledDeleteButtonProps
>(
(
{
tooltip: tooltipTitle,
tooltipDelay: enterDelay = 1000,
hideButton,
...props
},
ref,
) => {
if (hideButton) return null;

return (
<Tooltip enterDelay={enterDelay} title={tooltipTitle}>
<IconButton ref={ref} {...props} size="small" className="text-white">
<DeleteIcon />
</IconButton>
</Tooltip>
);
},
);

export default StyledDeleteButton;
44 changes: 44 additions & 0 deletions src/components/StyledListContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import AddIcon from "@mui/icons-material/Add";
import { Box, BoxProps, Button } from "@mui/material";
import React from "react";
import { useTranslation } from "react-i18next";

interface StyledListContainerProps extends BoxProps {
path: string;
verified?: boolean;
onAppend: () => void;
children: React.ReactNode;
}

const StyledListContainer: React.FC<StyledListContainerProps> = ({
path,
verified,
onAppend,
children,
...boxProps
}) => {
const t = useTranslation("labelDataValidator").t;
return (
<Box
className="flex flex-1 flex-col"
data-testid={`fields-container-${path}`}
{...boxProps}
>
{children}

{/* Add Row Button */}
<Button
size="small"
className={`!p-2 text-white bg-green-500 ${verified ? "!hidden" : ""}`}
onClick={onAppend}
startIcon={<AddIcon />}
disabled={verified}
data-testid={`add-button-${path}`}
>
{t("addRow")}
</Button>
</Box>
);
};

export default StyledListContainer;
17 changes: 14 additions & 3 deletions src/components/VerifiedFieldComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ interface VerifiedFieldWrapperProps {
valuePath: string;
verified: boolean;
}) => ReactNode;
validate?: (callback: (valid: boolean) => void) => Promise<void>;
}

export const VerifiedFieldWrapper: React.FC<VerifiedFieldWrapperProps> = ({
Expand All @@ -37,6 +38,7 @@ export const VerifiedFieldWrapper: React.FC<VerifiedFieldWrapperProps> = ({
className = "",
loading = false,
renderField,
validate,
}) => {
const { t } = useTranslation("labelDataValidator");
const { control } = useFormContext();
Expand All @@ -63,13 +65,16 @@ export const VerifiedFieldWrapper: React.FC<VerifiedFieldWrapperProps> = ({
data-testid={`verified-field-${path}`}
>
{renderField({ setIsFocused, control, valuePath, verified })}

{/* Vertical Divider */}
<Divider
orientation="vertical"
flexItem
className={isFocused ? "!border-fertiscan-blue" : ""}
sx={{ bgcolor: verified ? "#00C55E" : "inherit" }}
className={`${isFocused ? "!border-fertiscan-blue" : ""} ${verified ? "bg-green-500" : "bg-inherit"}`}
data-testid={`divider-${path}`}
/>

{/* Verified Toggle Button */}
<Controller
name={verifiedPath}
control={control}
Expand All @@ -83,7 +88,13 @@ export const VerifiedFieldWrapper: React.FC<VerifiedFieldWrapperProps> = ({
enterDelay={1000}
>
<IconButton
onClick={() => onChange(!value)}
onClick={() =>
validate
? validate((valid) => {
if (valid) onChange(!value);
})
: onChange(!value)
}
data-testid={`toggle-verified-btn-${verifiedPath}`}
aria-label={
verified
Expand Down
42 changes: 42 additions & 0 deletions src/components/VerifiedListRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Box, Divider } from "@mui/material";
import React from "react";
import { useTranslation } from "react-i18next";
import StyledDeleteButton from "./StyledDeleteButton";

interface VerifiedListRowProps {
verified?: boolean;
hideDelete?: boolean;
onDelete?: () => void;
isLastItem?: boolean;
children: React.ReactNode;
}

const VerifiedListRow: React.FC<VerifiedListRowProps> = ({
verified,
hideDelete,
onDelete,
isLastItem,
children,
}) => {
const { t } = useTranslation("labelDataValidator");
return (
<Box className="ml-2" data-testid={`field-row`}>
<Box className="flex items-center">
{children}

<StyledDeleteButton
tooltip={t("deleteVerifiedListRow")}
hideButton={verified || hideDelete}
onClick={onDelete}
data-testid={`delete-row-button`}
/>
</Box>

<Divider
className={`!my-1 ${verified ? "bg-green-500" : "bg-inherit"} ${isLastItem && verified ? "hidden" : ""}`}
/>
</Box>
);
};

export default VerifiedListRow;
Loading

0 comments on commit 42c8bf6

Please sign in to comment.