Browse Source

add create staff page

tags/Baseline_30082024_FRONTEND_UAT
MSI\derek 1 year ago
parent
commit
0e663929f1
5 changed files with 534 additions and 0 deletions
  1. +110
    -0
      src/app/(main)/staff/create/page.tsx
  2. +45
    -0
      src/components/CreateStaff/CreateStaffForm.tsx
  3. +1
    -0
      src/components/CreateStaff/index.ts
  4. +377
    -0
      src/components/CustomInputForm/CustomInputForm.tsx
  5. +1
    -0
      src/components/CustomInputForm/index.ts

+ 110
- 0
src/app/(main)/staff/create/page.tsx View File

@@ -0,0 +1,110 @@
// 'use client';
import { I18nProvider, getServerI18n } from "@/i18n";
import CustomInputForm from "@/components/CustomInputForm";
import Check from "@mui/icons-material/Check";
import Close from "@mui/icons-material/Close";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import Tab from "@mui/material/Tab";
import Tabs, { TabsProps } from "@mui/material/Tabs";
import { useRouter } from "next/navigation";
import React, { useCallback, useState } from "react";
import { useTranslation } from "react-i18next";
// import ProjectClientDetails from "./ProjectClientDetails";
// import TaskSetup from "./TaskSetup";
// import StaffAllocation from "./StaffAllocation";
// import ResourceMilestone from "./ResourceMilestone";
import { Task, TaskTemplate } from "@/app/api/tasks";
import {
FieldErrors,
FormProvider,
SubmitErrorHandler,
SubmitHandler,
useForm,
} from "react-hook-form";
import { CreateProjectInputs, saveProject } from "@/app/api/projects/actions";
import { Error } from "@mui/icons-material";
import { ProjectCategory } from "@/app/api/projects";
import { Staff } from "@/app/api/staff";
import { Grid, Typography } from "@mui/material";
import CreateStaffForm from "@/components/CreateStaff/CreateStaffForm";

// import { Metadata } from "next";

// export const metadata: Metadata = {
// title: "staffCreate",
// };

// export interface Props {
// allTasks: Task[];
// projectCategories: ProjectCategory[];
// taskTemplates: TaskTemplate[];
// teamLeads: Staff[];
// }
interface CreateCustomInputs {
projectCode: string;
projectName: string;
}
const createCustomInputs: CreateCustomInputs = {
// Project details
projectCode: "",
projectName: "",
}
// const Title = ["title1", "title2"];

const CreateStaff: React.FC = async () => {
const { t } = await getServerI18n("createStaff");

const fieldLists = [
[
{
id: "name",
label: t("Staff Name"),
type: "textfield",
value: "asdasd",
// required: "asdasd",
// option: "asdasd",
},
{
id: "date",
label: "date test",
type: "multiDate",
value: "asdasd",
// required: "asdasd",
// option: "asdasd",
},
{
id: "date2",
label: "combo test",
type: "combo-Obj",
value: "asdasd",
// required: "asdasd",
options: [{id: 1, key: 1, value: 1, label: "first"}, {id: 2, key: 1, value: 2, label: "second"}],
},
{
id: "field1",
label: "remarks test",
type: "remarks",
value: "",
// required: "asdasd",
// options: "asdasd",
},
],
];

const handleSubmit = (data: any) => {
console.log(data);
};

return (
<>
<Typography variant="h4">{t("Create Staff")}</Typography>
<I18nProvider namespaces={["createStaff"]}>
{/* <CreateStaffForm/>/ */}
<CreateStaffForm fieldLists={fieldLists}/>
</I18nProvider>
</>
);
};

export default CreateStaff;

+ 45
- 0
src/components/CreateStaff/CreateStaffForm.tsx View File

@@ -0,0 +1,45 @@
'use client'
import { useState } from 'react';
import CustomInputForm from '../CustomInputForm';

interface Field {
// subtitle: string;
id: string;
label: string;
type: string;
value?: any;
required?: boolean;
options?: any[];
readOnly?: boolean;
}

interface formProps {
// onSubmit: (data: any) => void;
// resetForm: () => void;
// Title?: string[];
// isActive: boolean;
fieldLists: Field[][];
}

const CreateStaffForm: React.FC<formProps> = ({
fieldLists
}) => {
// const [formData, setFormData] = useState<any>(null);

const handleSubmit = (data: any) => {
console.log(data);
// Handle the form submission logic here
// setFormData(data);
};

return (
<CustomInputForm
// Pass other props to CustomInputForm as needed
fieldLists={fieldLists}
isActive={true}
onSubmit={handleSubmit}
/>
);
};

export default CreateStaffForm;

+ 1
- 0
src/components/CreateStaff/index.ts View File

@@ -0,0 +1 @@
export { default } from "./CreateStaffForm";

+ 377
- 0
src/components/CustomInputForm/CustomInputForm.tsx View File

@@ -0,0 +1,377 @@
"use client";
import {
Card,
CardHeader,
CardContent,
SxProps,
Theme,
Typography,
Grid,
TextField,
FormControl,
InputLabel,
Select,
MenuItem,
Checkbox,
FormControlLabel,
Button,
} from "@mui/material";
import { DataGrid, GridColDef, GridRowSelectionModel } from "@mui/x-data-grid";
import { darken, lighten, styled } from "@mui/material/styles";
import { Controller, useForm, useFormContext } from "react-hook-form";
import Stack from "@mui/material/Stack";
import { useTranslation } from "react-i18next";
import Box from "@mui/material/Box";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { DemoItem } from "@mui/x-date-pickers/internals/demo";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import dayjs from "dayjs";
import { useEffect, useState } from "react";
import { Check } from "@mui/icons-material";

// interface Option {
// // Define properties of each option object
// // based on your specific requirements
// id: any;
// value: any;
// label: string;
// }

interface Field {
// subtitle: string;
id: string;
label: string;
type: string;
value?: any;
required?: boolean;
options?: any[];
readOnly?: boolean;
}

interface CustomInputFormProps {
onSubmit: (data: any) => void;
// resetForm: () => void;
Title?: string[];
isActive: boolean;
fieldLists: Field[][];
}

const CustomInputForm: React.FC<CustomInputFormProps> = ({
Title,
isActive,
fieldLists,
onSubmit,
// resetForm,
}) => {
const { t } = useTranslation();
const { reset, register, handleSubmit, control } = useForm();
const [dateObj, setDateObj] = useState<any>(null);
const [value, setValue] = useState<any>({});
const [checkboxValue, setCheckboxValue] = useState({});
// const [dateObj, setDateObj] = useState({});

interface DateObj {
[key: string]: string;
}

const handleFormSubmit = (data: any) => {
// if (date != null || date != undefined ) {
// data.date = dayjs(date).format('YYYY-MM-DD');
// }
for (const key in data) {
if (!isNaN(data[key])) {
if (data[key] !== "") {
if (Number.isInteger(parseFloat(data[key]))) {
data[key] = parseInt(data[key]);
} else {
data[key] = parseFloat(data[key]);
}
}
}
}

if (checkboxValue !== null) {
data = { ...data, ...checkboxValue };
}

// if (value !== null) {
// data.dropdownCombo = value;
// }
const finalData = {
...value,
...data,
...dateObj,
};

console.log(finalData);
onSubmit(finalData);
};

const handleDateChange = (id: string, newValue: dayjs.Dayjs | null): void => {
console.log(dayjs(newValue).format("YYYY-MM-DD"));
setDateObj((prevValues: DateObj) => ({
...prevValues,
[id]: newValue ? dayjs(newValue).format("YYYY-MM-DD") : "",
}));
};

const handleCheckboxChange = (id: string, newValue: boolean): void => {
setCheckboxValue((prevValues: { [key: string]: boolean }) => ({
...prevValues,
[id]: newValue,
}));
};

const handleAutocompleteChange = (id: any, newValue: any) => {
setValue((prevValues: any) => ({
...prevValues,
[id]: newValue,
}));
};

fieldLists.forEach((list) => {
list.forEach((obj) => {
if (
obj.id === "created" ||
obj.id === "createdBy" ||
obj.id === "modified" ||
obj.id === "deleted" ||
obj.id === "modifiedBy"
) {
obj.readOnly = true;
}
});
});

// useEffect(() => {
// if (dateObj) {
// console.log(dateObj);
// }
// }, [dateObj]);

return (
<form onSubmit={handleSubmit(handleFormSubmit)}>
<Card sx={{ display: isActive ? "block" : "none" }}>
<CardContent component={Stack} spacing={4}>
<>
{fieldLists.map((fieldList, fieldListIndex) => (
<Box key={fieldListIndex}>
{Title ? (
<Typography
variant="overline"
display="block"
marginBlockEnd={1}
>
{t(`${Title[fieldListIndex]}`)}
</Typography>
) : null}
<Grid container spacing={2} columns={{ xs: 6, sm: 12 }}>
{fieldList.map((field: Field) => {
if (field.type === "textfield") {
return (
<Grid item xs={6} key={field.id}>
<TextField
label={t(`${field.label}`)}
fullWidth
// {...register(`asdasd`, {
{...register(`${field.id}`, {
required: field.required ?? false,
})}
// error={Boolean(errors.projectCode)}
/>
</Grid>
);
} else if (field.type === "multiDate") {
return (
<Grid item xs={6} key={field.id}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DemoItem>
<DatePicker
key={field.id}
label={field.label}
value={!dateObj ? null : !dateObj[field.id] ? null : dayjs(dateObj[field.id])} // Set initial value or use a default value from state
onChange={(newValue) => {
handleDateChange(field.id, newValue);
}}
// required = {field.required ?? false},
/>
</DemoItem>
</LocalizationProvider>
</Grid>
);
} else if (field.type === "combo-Obj") {
return (
<Grid item xs={6} key={field.id}>
<FormControl fullWidth>
<InputLabel id={`${field.id}-label`}>
{field.label}
</InputLabel>
<Controller
name={field.id}
control={control}
defaultValue={
field.value !== undefined ? field.value : ""
}
render={({ field: { onChange, value } }) => (
<Select
labelId={`${field.id}-label`}
id={field.id}
value={value}
onChange={(event) => {
console.log(event);
console.log(event.target);
onChange(event.target.value);
const newValue = event.target.value;
const selectedOption = field.options?.find(
(option) => option.id === newValue
);
handleAutocompleteChange(
field.id,
selectedOption
);
}}
required={field.required}
>
{field.options?.map((option) => (
<MenuItem
value={
option.id !== undefined
? option.id
: option
}
key={
option.id !== undefined
? option.id
: option
}
>
{option.id !== undefined
? option.label
: option}
</MenuItem>
))}
</Select>
)}
/>
</FormControl>
</Grid>
);
} else if (field.type === "numeric") {
return (
<Grid item xs={6} key={field.id}>
<TextField
fullWidth
{...register(field.id)}
id={field.id}
label={field.label}
defaultValue={!field.value ? `${field.value}` : ""}
inputProps={{
inputMode: "numeric",
pattern: "^-?\\d*\\.?\\d+$",
}}
required={field.required}
/>
</Grid>
);
} else if (field.type === "numeric-positive") {
return (
<Grid item xs={6} key={field.id}>
<TextField
fullWidth
{...register(field.id)}
id={field.id}
label={field.label}
defaultValue={!field.value ? `${field.value}` : ""}
inputProps={{
inputMode: "numeric",
pattern: "[0-9]*[.]?[0-9]*",
}}
required={field.required}
/>
</Grid>
);
} else if (field.type === "checkbox") {
return (
<Grid item xs={6} key={field.id}>
<FormControlLabel
control={
<Checkbox
defaultChecked={field.value}
onChange={(event) => {
handleCheckboxChange(
field.id,
event.target.checked
);
}}
color="primary"
/>
}
label={
<Typography variant="h4">
{field.label}
</Typography>
}
/>
</Grid>
);
} else if (field.type === "remarks") {
return (
<Grid item xs={12} key={field.id}>
<TextField
fullWidth
multiline
rows={4}
variant="filled"
{...register(field.id)}
defaultValue={!field.value ? `${field.value}` : ""}
id={field.id}
label={field.label}
required={field.required}
/>
</Grid>
);
} else {
return (
<Grid item xs={6} key={field.id}>
<TextField
fullWidth
{...register(
field.id
// , { required: true }
)}
id={field.id}
label={field.label}
defaultValue={`${field.value}`}
required={field.required}
inputProps={{
readOnly: field.readOnly,
}}
/>
</Grid>
);
}
})}
</Grid>
</Box>
))}
<Stack direction="row" justifyContent="flex-end" gap={1}>
{/* <Button
variant="outlined"
startIcon={<Close />}
onClick={handleCancel}
>
{t("Cancel")}
</Button> */}
<Button variant="contained" startIcon={<Check />} type="submit">
{t("Confirm")}
</Button>
</Stack>
</>
</CardContent>
</Card>
</form>
);
};

export default CustomInputForm;

+ 1
- 0
src/components/CustomInputForm/index.ts View File

@@ -0,0 +1 @@
export { default } from "./CustomInputForm";

Loading…
Cancel
Save