@@ -0,0 +1,25 @@ | |||||
import { Edit } from "@mui/icons-material"; | |||||
import { useSearchParams } from "next/navigation"; | |||||
// import EditStaff from "@/components/EditStaff"; | |||||
import { Suspense } from "react"; | |||||
import { I18nProvider } from "@/i18n"; | |||||
// import EditStaffWrapper from "@/components/EditStaff/EditStaffWrapper"; | |||||
import { Metadata } from "next"; | |||||
import EditTeam from "@/components/EditTeam"; | |||||
const EditTeamPage: React.FC = () => { | |||||
return ( | |||||
<> | |||||
<I18nProvider namespaces={["team", "common"]}> | |||||
<Suspense fallback={<EditTeam.Loading />}> | |||||
<EditTeam /> | |||||
</Suspense> | |||||
</I18nProvider> | |||||
{/* <EditStaff /> */} | |||||
</> | |||||
); | |||||
}; | |||||
export default EditTeamPage; |
@@ -3,6 +3,7 @@ import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||||
import { BASE_API_URL } from "@/config/api"; | import { BASE_API_URL } from "@/config/api"; | ||||
import { StaffResult, data } from "."; | import { StaffResult, data } from "."; | ||||
import { cache } from "react"; | import { cache } from "react"; | ||||
import { Team, staff } from "../team/actions"; | |||||
export interface CreateCustomInputs { | export interface CreateCustomInputs { | ||||
// Project details | // Project details | ||||
projectCode: string; | projectCode: string; | ||||
@@ -28,11 +29,20 @@ export interface CreateStaffInputs { | |||||
emergContactPhone: string; | emergContactPhone: string; | ||||
employType: string; | employType: string; | ||||
joinDate: string | null; | joinDate: string | null; | ||||
departDate: string | null; | |||||
departReason: string | null; | |||||
remark: string | null; | |||||
departDate?: string | null; | |||||
departReason?: string | null; | |||||
remark?: string | null; | |||||
} | } | ||||
export interface records { | |||||
id: number; | |||||
name: string; | |||||
// team: Team[]; | |||||
} | |||||
export interface Staff4TransferList { | |||||
records: records[]; | |||||
} | |||||
export const saveStaff = async (data: CreateStaffInputs) => { | export const saveStaff = async (data: CreateStaffInputs) => { | ||||
return serverFetchJson(`${BASE_API_URL}/staffs/save`, { | return serverFetchJson(`${BASE_API_URL}/staffs/save`, { | ||||
method: "POST", | method: "POST", | ||||
@@ -68,3 +78,9 @@ export const fetchStaffEdit = cache(async (id: number) => { | |||||
// fetchStaffEdit(id); | // fetchStaffEdit(id); | ||||
// }; | // }; | ||||
export const fetchStaffCombo = cache(async () => { | |||||
return serverFetchJson<Staff4TransferList>(`${BASE_API_URL}/staffs/combo`, { | |||||
next: { tags: ["staffs"] }, | |||||
}); | |||||
}); | |||||
@@ -6,6 +6,26 @@ import "server-only"; | |||||
export interface data { | export interface data { | ||||
[key: string]: any; | [key: string]: any; | ||||
} | } | ||||
export interface StaffGroup { | |||||
id: number; | |||||
name: string; | |||||
} | |||||
export interface Staff { | |||||
id: number; | |||||
staffId: string; | |||||
name: string; | |||||
// description: string | null; | |||||
currentPosition: StaffGroup; | |||||
} | |||||
export interface StaffTeamTable { | |||||
id: number; | |||||
staffId: string; | |||||
name: string; | |||||
// description: string | null; | |||||
currentPosition: string; | |||||
} | |||||
export interface StaffResult { | export interface StaffResult { | ||||
action: any; | action: any; | ||||
id: number; | id: number; | ||||
@@ -16,6 +36,8 @@ export interface StaffResult { | |||||
joinPosition: string; | joinPosition: string; | ||||
currentPosition: string; | currentPosition: string; | ||||
data: data; | data: data; | ||||
teamId: number; | |||||
staffName: string; | |||||
} | } | ||||
export interface searchInput { | export interface searchInput { | ||||
staffId: string; | staffId: string; | ||||
@@ -44,3 +66,9 @@ export const fetchStaff = cache(async () => { | |||||
next: { tags: ["staffs"] }, | next: { tags: ["staffs"] }, | ||||
}); | }); | ||||
}); | }); | ||||
// export const fetchStaffCombo = cache(async () => { | |||||
// return serverFetchJson<Staff4TransferList>(`${BASE_API_URL}/staffs/combo`, { | |||||
// next: { tags: ["staffs"] }, | |||||
// }); | |||||
// }); |
@@ -16,9 +16,6 @@ import { useCallback } from "react"; | |||||
import { CreateTeamInputs } from "@/app/api/team/actions"; | import { CreateTeamInputs } from "@/app/api/team/actions"; | ||||
const TeamInfo: React.FC = ( | const TeamInfo: React.FC = ( | ||||
{ | |||||
// customerTypes, | |||||
} | |||||
) => { | ) => { | ||||
const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
const { | const { | ||||
@@ -36,7 +33,7 @@ const TeamInfo: React.FC = ( | |||||
resetField("description"); | resetField("description"); | ||||
} | } | ||||
}, [defaultValues]); | }, [defaultValues]); | ||||
return ( | return ( | ||||
<> | <> | ||||
<Card sx={{ display: "block" }}> | <Card sx={{ display: "block" }}> | ||||
@@ -0,0 +1,263 @@ | |||||
"use client"; | |||||
import React, { useCallback, useEffect, useMemo, useState } from "react"; | |||||
import CustomInputForm from "../CustomInputForm"; | |||||
import { useRouter, useSearchParams } from "next/navigation"; | |||||
import { useTranslation } from "react-i18next"; | |||||
import { | |||||
FieldErrors, | |||||
FormProvider, | |||||
SubmitErrorHandler, | |||||
SubmitHandler, | |||||
useForm, | |||||
useFormContext, | |||||
} from "react-hook-form"; | |||||
import { CreateTeamInputs } from "@/app/api/team/actions"; | |||||
import { Staff4TransferList, fetchStaffCombo } from "@/app/api/staff/actions"; | |||||
import { StaffResult, StaffTeamTable } from "@/app/api/staff"; | |||||
import SearchResults, { Column } from "../SearchResults"; | |||||
import { Clear, PersonAdd, PersonRemove, Search } from "@mui/icons-material"; | |||||
import { Card } from "reactstrap"; | |||||
import { | |||||
Box, | |||||
CardContent, | |||||
Grid, | |||||
IconButton, | |||||
InputAdornment, | |||||
Stack, | |||||
Tab, | |||||
Tabs, | |||||
TabsProps, | |||||
TextField, | |||||
Typography, | |||||
} from "@mui/material"; | |||||
import { differenceBy } from "lodash"; | |||||
import StarsIcon from "@mui/icons-material/Stars"; | |||||
export interface Props { | |||||
allStaffs: StaffResult[]; | |||||
} | |||||
const Allocation: React.FC<Props> = ({ allStaffs: staff }) => { | |||||
const { t } = useTranslation(); | |||||
const searchParams = useSearchParams(); | |||||
const idString = searchParams.get("id"); | |||||
const { | |||||
setValue, | |||||
getValues, | |||||
formState: { defaultValues }, | |||||
reset, | |||||
resetField, | |||||
} = useFormContext<CreateTeamInputs>(); | |||||
// let firstFilter: StaffResult[] = [] | |||||
const initialStaffs = staff.map((s) => ({ ...s })); | |||||
const [filteredStaff, setFilteredStaff] = useState(initialStaffs); | |||||
const [selectedStaff, setSelectedStaff] = useState<typeof filteredStaff>( | |||||
filteredStaff.filter((s) => getValues("addStaffIds")?.includes(s.id)) | |||||
); | |||||
const [seletedTeamLead, setSeletedTeamLead] = useState<number>(); | |||||
const [deletedStaffIds, setDeletedStaffIds] = useState<number[]>([]); | |||||
// Adding / Removing staff | |||||
const addStaff = useCallback((staff: StaffResult) => { | |||||
setSelectedStaff((s) => [...s, staff]); | |||||
// setDeletedStaffIds((s) => s.filter((s) => s === selectedStaff.id)) | |||||
}, []); | |||||
const removeStaff = useCallback((staff: StaffResult) => { | |||||
setSelectedStaff((s) => s.filter((s) => s.id !== staff.id)); | |||||
setDeletedStaffIds((s) => s) | |||||
// setValue("deleteStaffIds", [...staff.id]) | |||||
}, []); | |||||
const setTeamLead = useCallback( | |||||
(staff: StaffResult) => { | |||||
setSeletedTeamLead(staff.id); | |||||
const rearrangedList = getValues("addStaffIds").reduce<number[]>( | |||||
(acc, num, index) => { | |||||
if (num === staff.id && index !== 0) { | |||||
acc.splice(index, 1); | |||||
acc.unshift(num); | |||||
} | |||||
return acc; | |||||
}, | |||||
getValues("addStaffIds") | |||||
); | |||||
console.log(rearrangedList); | |||||
console.log(selectedStaff); | |||||
const rearrangedStaff = rearrangedList.map((id) => { | |||||
return selectedStaff.find((staff) => staff.id === id); | |||||
}); | |||||
console.log(rearrangedStaff); | |||||
setSelectedStaff(rearrangedStaff as StaffResult[]); | |||||
setValue("addStaffIds", rearrangedList); | |||||
}, | |||||
[addStaff, selectedStaff] | |||||
); | |||||
const clearSubsidiary = useCallback(() => { | |||||
if (defaultValues !== undefined) { | |||||
resetField("addStaffIds"); | |||||
setSelectedStaff( | |||||
initialStaffs.filter((s) => defaultValues.addStaffIds?.includes(s.id)) | |||||
); | |||||
} | |||||
}, [defaultValues]); | |||||
// Sync with form | |||||
useEffect(() => { | |||||
setValue( | |||||
"addStaffIds", | |||||
selectedStaff.map((s) => s.id) | |||||
); | |||||
}, [selectedStaff, setValue]); | |||||
useEffect(() => { | |||||
setValue("deleteStaffIds", deletedStaffIds) | |||||
console.log(deletedStaffIds) | |||||
}, [deletedStaffIds, setValue]); | |||||
const StaffPoolColumns = useMemo<Column<StaffResult>[]>( | |||||
() => [ | |||||
{ | |||||
label: t("Add"), | |||||
name: "id", | |||||
onClick: addStaff, | |||||
buttonIcon: <PersonAdd />, | |||||
}, | |||||
{ label: t("Staff Id"), name: "staffId" }, | |||||
{ label: t("Staff Name"), name: "name" }, | |||||
{ label: t("Current Position"), name: "currentPosition" }, | |||||
], | |||||
[addStaff, t] | |||||
); | |||||
const allocatedStaffColumns = useMemo<Column<StaffResult>[]>( | |||||
() => [ | |||||
{ | |||||
label: t("Remove"), | |||||
name: "action", | |||||
onClick: removeStaff, | |||||
buttonIcon: <PersonRemove />, | |||||
}, | |||||
{ label: t("Staff Id"), name: "staffId" }, | |||||
{ label: t("Staff Name"), name: "name" }, | |||||
{ label: t("Current Position"), name: "currentPosition" }, | |||||
{ | |||||
label: t("Team Lead"), | |||||
name: "action", | |||||
onClick: setTeamLead, | |||||
buttonIcon: <StarsIcon />, | |||||
}, | |||||
], | |||||
[removeStaff, selectedStaff, t] | |||||
); | |||||
const [query, setQuery] = React.useState(""); | |||||
const onQueryInputChange = React.useCallback< | |||||
React.ChangeEventHandler<HTMLInputElement> | |||||
>((e) => { | |||||
setQuery(e.target.value); | |||||
}, []); | |||||
const clearQueryInput = React.useCallback(() => { | |||||
setQuery(""); | |||||
}, []); | |||||
React.useEffect(() => { | |||||
// setFilteredStaff( | |||||
// initialStaffs.filter((s) => { | |||||
// const q = query.toLowerCase(); | |||||
// // s.staffId.toLowerCase().includes(q) | |||||
// // const q = query.toLowerCase(); | |||||
// // return s.name.toLowerCase().includes(q); | |||||
// // s.code.toString().includes(q) || | |||||
// // (s.brNo != null && s.brNo.toLowerCase().includes(q)) | |||||
// }) | |||||
// ); | |||||
}, [staff, query]); | |||||
useEffect(() => { | |||||
// console.log(getValues("addStaffIds")) | |||||
}, [initialStaffs]); | |||||
const resetStaff = React.useCallback(() => { | |||||
clearQueryInput(); | |||||
clearSubsidiary(); | |||||
}, [clearQueryInput, clearSubsidiary]); | |||||
const formProps = useForm({}); | |||||
// Tab related | |||||
const [tabIndex, setTabIndex] = React.useState(0); | |||||
const handleTabChange = React.useCallback<NonNullable<TabsProps["onChange"]>>( | |||||
(_e, newValue) => { | |||||
setTabIndex(newValue); | |||||
}, | |||||
[] | |||||
); | |||||
return ( | |||||
<> | |||||
<FormProvider {...formProps}> | |||||
<Card sx={{ display: "block" }}> | |||||
<CardContent | |||||
sx={{ display: "flex", flexDirection: "column", gap: 1 }} | |||||
> | |||||
<Stack gap={2}> | |||||
<Typography variant="overline" display="block"> | |||||
{t("staff")} | |||||
</Typography> | |||||
<Grid container spacing={2} columns={{ xs: 6, sm: 12 }}> | |||||
<Grid item xs={6} display="flex" alignItems="center"> | |||||
<Search sx={{ marginInlineEnd: 1 }} /> | |||||
<TextField | |||||
variant="standard" | |||||
fullWidth | |||||
onChange={onQueryInputChange} | |||||
value={query} | |||||
placeholder={t("Search by staff ID, name or position.")} | |||||
InputProps={{ | |||||
endAdornment: query && ( | |||||
<InputAdornment position="end"> | |||||
<IconButton onClick={clearQueryInput}> | |||||
<Clear /> | |||||
</IconButton> | |||||
</InputAdornment> | |||||
), | |||||
}} | |||||
/> | |||||
</Grid> | |||||
</Grid> | |||||
<Tabs value={tabIndex} onChange={handleTabChange}> | |||||
<Tab label={t("Staff Pool")} /> | |||||
<Tab | |||||
label={`${t("Allocated Staff")} (${selectedStaff.length})`} | |||||
/> | |||||
</Tabs> | |||||
<Box sx={{ marginInline: -3 }}> | |||||
{tabIndex === 0 && ( | |||||
<SearchResults | |||||
noWrapper | |||||
items={differenceBy(filteredStaff, selectedStaff, "id")} | |||||
columns={StaffPoolColumns} | |||||
/> | |||||
)} | |||||
{tabIndex === 1 && ( | |||||
<SearchResults | |||||
noWrapper | |||||
items={selectedStaff} | |||||
columns={allocatedStaffColumns} | |||||
/> | |||||
)} | |||||
</Box> | |||||
</Stack> | |||||
</CardContent> | |||||
</Card> | |||||
</FormProvider> | |||||
</> | |||||
); | |||||
}; | |||||
export default Allocation; |
@@ -0,0 +1,204 @@ | |||||
"use client"; | |||||
import { useRouter, useSearchParams } from "next/navigation"; | |||||
import { useCallback, useEffect, useMemo, useState } from "react"; | |||||
import SearchResults, { Column } from "../SearchResults"; | |||||
// import { TeamResult } from "@/app/api/team"; | |||||
import { useTranslation } from "react-i18next"; | |||||
import { Button, Stack, Tab, Tabs, TabsProps, Typography } from "@mui/material"; | |||||
import { CreateTeamInputs, saveTeam } from "@/app/api/team/actions"; | |||||
import { | |||||
FieldErrors, | |||||
FormProvider, | |||||
SubmitHandler, | |||||
useForm, | |||||
useFormContext, | |||||
} from "react-hook-form"; | |||||
import { Check, Close, Error } from "@mui/icons-material"; | |||||
import TeamInfo from "../EditTeam/TeamInfo"; | |||||
import Allocation from "./Allocation"; | |||||
import { StaffResult } from "@/app/api/staff"; | |||||
interface desc { | |||||
id: number; | |||||
description: string; | |||||
} | |||||
interface Props { | |||||
staff: StaffResult[]; | |||||
desc: desc[]; | |||||
} | |||||
const EditTeam: React.FC<Props> = async ({ staff, desc }) => { | |||||
// console.log(desc) | |||||
const { t } = useTranslation(); | |||||
const formProps = useForm<CreateTeamInputs>(); | |||||
const searchParams = useSearchParams(); | |||||
const idString = searchParams.get("id"); | |||||
const [filteredItems, setFilteredItems] = useState<StaffResult[]>(); | |||||
const [allStaffs, setAllStaffs] = useState<StaffResult[]>(); | |||||
const [filteredDesc, setFilteredDesc] = useState<string>(); | |||||
const [tabIndex, setTabIndex] = useState(0); | |||||
const router = useRouter(); | |||||
// const [selectedStaff, setSelectedStaff] = useState<typeof filteredItems>( | |||||
// initialStaffs.filter((s) => getValues("addStaffIds")?.includes(s.id)) | |||||
// ); | |||||
const errors = formProps.formState.errors; | |||||
const handleTabChange = useCallback<NonNullable<TabsProps["onChange"]>>( | |||||
(_e, newValue) => { | |||||
setTabIndex(newValue); | |||||
}, | |||||
[] | |||||
); | |||||
const [serverError, setServerError] = useState(""); | |||||
const cols = useMemo<Column<StaffResult>[]>( | |||||
() => [ | |||||
{ label: t("Staff Id"), name: "staffId" }, | |||||
{ label: t("Name"), name: "staffName" }, | |||||
// { label: t("Current Position"), name: "posCode" }, | |||||
], | |||||
[t] | |||||
); | |||||
useEffect(() => { | |||||
let idList: number[] = [] | |||||
if (idString) { | |||||
const filteredTeam = staff.filter( | |||||
(item) => item.teamId === parseInt(idString) | |||||
); | |||||
const tempDesc = desc.filter( | |||||
(item) => item.id === parseInt(idString) | |||||
) | |||||
// console.log(filteredTeam); | |||||
if (filteredTeam.length > 0) { | |||||
const filteredIds: number[] = filteredTeam.map((i) => ( | |||||
i.id | |||||
)) | |||||
idList = filteredIds | |||||
} | |||||
// console.log(filteredIds) | |||||
setFilteredItems(filteredTeam); | |||||
formProps.reset({description: tempDesc[0].description, addStaffIds: idList}) | |||||
setFilteredDesc(tempDesc[0].description) | |||||
} | |||||
// console.log(staff); | |||||
// const desc = staff[0]?.description | |||||
// setDesc(desc) | |||||
// const staff = staff.map((item) => { | |||||
// return { | |||||
// id: item.id, | |||||
// name: item.name, | |||||
// staffId: item.staffId, | |||||
// teamId: item.teamId, | |||||
// staffName: item.staffName, | |||||
// currentPosition: item.currentPosition | |||||
// } as StaffResult | |||||
// }) | |||||
console.log(staff) | |||||
setAllStaffs(staff) | |||||
}, [searchParams]); | |||||
// useEffect(() => { | |||||
// console.log(allStaffs) | |||||
// }, [allStaffs]); | |||||
const hasErrorsInTab = ( | |||||
tabIndex: number, | |||||
errors: FieldErrors<CreateTeamInputs> | |||||
) => { | |||||
switch (tabIndex) { | |||||
case 0: | |||||
return Object.keys(errors).length > 0; | |||||
default: | |||||
false; | |||||
} | |||||
}; | |||||
const onSubmit = useCallback<SubmitHandler<CreateTeamInputs>>( | |||||
async (data) => { | |||||
try { | |||||
console.log(data); | |||||
const tempData = { | |||||
description: data.description, | |||||
addStaffIds: data.addStaffIds, | |||||
id: parseInt(idString!!) | |||||
} | |||||
console.log(tempData) | |||||
// await saveTeam(tempData); | |||||
// router.replace("/settings/staff"); | |||||
} catch (e) { | |||||
console.log(e); | |||||
setServerError(t("An error has occurred. Please try again later.")); | |||||
} | |||||
}, | |||||
[router] | |||||
); | |||||
return ( | |||||
<> | |||||
{serverError && ( | |||||
<Typography variant="body2" color="error" alignSelf="flex-end"> | |||||
{serverError} | |||||
</Typography> | |||||
)} | |||||
<FormProvider {...formProps}> | |||||
<Stack | |||||
spacing={2} | |||||
component="form" | |||||
onSubmit={formProps.handleSubmit(onSubmit)} | |||||
> | |||||
<Typography variant="h4" marginInlineEnd={2}> | |||||
{t("Edit Team")} | |||||
</Typography> | |||||
<Stack | |||||
direction="row" | |||||
justifyContent="space-between" | |||||
flexWrap="wrap" | |||||
rowGap={2} | |||||
> | |||||
<Tabs | |||||
value={tabIndex} | |||||
onChange={handleTabChange} | |||||
variant="scrollable" | |||||
> | |||||
<Tab | |||||
label={t("Team Info")} | |||||
icon={ | |||||
hasErrorsInTab(0, errors) ? ( | |||||
<Error sx={{ marginInlineEnd: 1 }} color="error" /> | |||||
) : undefined | |||||
} | |||||
iconPosition="end" | |||||
/> | |||||
<Tab label={t("Staff Allocation")} iconPosition="end" /> | |||||
</Tabs> | |||||
</Stack> | |||||
{tabIndex === 0 && <TeamInfo value={filteredDesc!!} />} | |||||
{tabIndex === 1 && <Allocation allStaffs={allStaffs!!} />} | |||||
<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" | |||||
// disabled={Boolean(formProps.watch("isGridEditing"))} | |||||
> | |||||
{t("Confirm")} | |||||
</Button> | |||||
</Stack> | |||||
</Stack> | |||||
</FormProvider> | |||||
</> | |||||
); | |||||
}; | |||||
export default EditTeam; |
@@ -0,0 +1,40 @@ | |||||
import Card from "@mui/material/Card"; | |||||
import CardContent from "@mui/material/CardContent"; | |||||
import Skeleton from "@mui/material/Skeleton"; | |||||
import Stack from "@mui/material/Stack"; | |||||
import React from "react"; | |||||
// Can make this nicer | |||||
export const EditTeamLoading: React.FC = () => { | |||||
return ( | |||||
<> | |||||
<Card> | |||||
<CardContent> | |||||
<Stack spacing={2}> | |||||
<Skeleton variant="rounded" height={60} /> | |||||
<Skeleton variant="rounded" height={60} /> | |||||
<Skeleton variant="rounded" height={60} /> | |||||
<Skeleton | |||||
variant="rounded" | |||||
height={50} | |||||
width={100} | |||||
sx={{ alignSelf: "flex-end" }} | |||||
/> | |||||
</Stack> | |||||
</CardContent> | |||||
</Card> | |||||
<Card>EditTeam | |||||
<CardContent> | |||||
<Stack spacing={2}> | |||||
<Skeleton variant="rounded" height={40} /> | |||||
<Skeleton variant="rounded" height={40} /> | |||||
<Skeleton variant="rounded" height={40} /> | |||||
<Skeleton variant="rounded" height={40} /> | |||||
</Stack> | |||||
</CardContent> | |||||
</Card> | |||||
</> | |||||
); | |||||
}; | |||||
export default EditTeamLoading; |
@@ -0,0 +1,29 @@ | |||||
import React from "react"; | |||||
import EditTeam from "./EditTeam"; | |||||
import EditTeamLoading from "./EditTeamLoading"; | |||||
// import { fetchTeam, fetchTeamLeads } from "@/app/api/Team"; | |||||
import { useSearchParams } from "next/navigation"; | |||||
import { fetchTeam, fetchTeamDetail } from "@/app/api/team"; | |||||
import { fetchStaff } from "@/app/api/staff"; | |||||
interface SubComponents { | |||||
Loading: typeof EditTeamLoading; | |||||
} | |||||
const EditTeamWrapper: React.FC & SubComponents = async () => { | |||||
const staff = await fetchStaff() | |||||
const allTeams = await fetchTeam(); | |||||
const teamDesc = allTeams.map((i) => ( | |||||
{ | |||||
id: i.id, | |||||
description: i.description | |||||
} | |||||
)) | |||||
console.log(staff) | |||||
console.log(teamDesc) | |||||
return <EditTeam staff={staff} desc={teamDesc}/>; | |||||
}; | |||||
EditTeamWrapper.Loading = EditTeamLoading; | |||||
export default EditTeamWrapper; |
@@ -0,0 +1,74 @@ | |||||
"use client"; | |||||
import Stack from "@mui/material/Stack"; | |||||
import Box from "@mui/material/Box"; | |||||
import Card from "@mui/material/Card"; | |||||
import CardContent from "@mui/material/CardContent"; | |||||
import Grid from "@mui/material/Grid"; | |||||
import TextField from "@mui/material/TextField"; | |||||
import Typography from "@mui/material/Typography"; | |||||
import { useTranslation } from "react-i18next"; | |||||
import CardActions from "@mui/material/CardActions"; | |||||
import RestartAlt from "@mui/icons-material/RestartAlt"; | |||||
import Button from "@mui/material/Button"; | |||||
import { Controller, useFormContext } from "react-hook-form"; | |||||
import { FormControl, InputLabel, MenuItem, Select } from "@mui/material"; | |||||
import { useCallback } from "react"; | |||||
import { CreateTeamInputs } from "@/app/api/team/actions"; | |||||
interface Props { | |||||
value: string; | |||||
} | |||||
const TeamInfo: React.FC<Props> = ( | |||||
{ | |||||
value | |||||
} | |||||
) => { | |||||
const { t } = useTranslation(); | |||||
const { | |||||
register, | |||||
formState: { errors, defaultValues }, | |||||
control, | |||||
reset, | |||||
resetField, | |||||
setValue, | |||||
} = useFormContext<CreateTeamInputs>(); | |||||
const resetCustomer = useCallback(() => { | |||||
console.log(defaultValues); | |||||
if (defaultValues !== undefined) { | |||||
resetField("description"); | |||||
} | |||||
}, [defaultValues]); | |||||
return ( | |||||
<> | |||||
<Card sx={{ display: "block" }}> | |||||
<CardContent component={Stack} spacing={4}> | |||||
<Box> | |||||
<Typography variant="overline" display="block" marginBlockEnd={1}> | |||||
{t("Team Info")} | |||||
</Typography> | |||||
<Grid container spacing={2} columns={{ xs: 6, sm: 12 }}> | |||||
<Grid item xs={12}> | |||||
<TextField | |||||
label={t("Team Description")} | |||||
fullWidth | |||||
multiline | |||||
rows={4} | |||||
{...register("description", { | |||||
required: true, | |||||
})} | |||||
defaultValue={value} | |||||
error={Boolean(errors.description)} | |||||
helperText={Boolean(errors.description) && (errors.description?.message ? t(errors.description.message) : t("Please input correct description"))} | |||||
/> | |||||
</Grid> | |||||
</Grid> | |||||
</Box> | |||||
</CardContent> | |||||
</Card> | |||||
</> | |||||
); | |||||
}; | |||||
export default TeamInfo; |
@@ -0,0 +1 @@ | |||||
export { default } from "./EditTeamWrapper"; |
@@ -2,7 +2,7 @@ | |||||
import { TeamResult } from "@/app/api/team"; | import { TeamResult } from "@/app/api/team"; | ||||
import SearchBox, { Criterion } from "../SearchBox"; | import SearchBox, { Criterion } from "../SearchBox"; | ||||
import { useMemo, useState } from "react"; | |||||
import { useCallback, useMemo, useState } from "react"; | |||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import SearchResults, { Column } from "../SearchResults/index"; | import SearchResults, { Column } from "../SearchResults/index"; | ||||
import EditNote from "@mui/icons-material/EditNote"; | import EditNote from "@mui/icons-material/EditNote"; | ||||
@@ -44,14 +44,20 @@ const TeamSearch: React.FC<Props> = ({ team }) => { | |||||
[t], | [t], | ||||
); | ); | ||||
const onTeamClick = useCallback((team: TeamResult) => { | |||||
console.log(team); | |||||
const id = team.id | |||||
router.push(`/settings/team/edit?id=${id}`); | |||||
}, [router, t]); | |||||
const columns = useMemo<Column<TeamResult>[]>( | const columns = useMemo<Column<TeamResult>[]>( | ||||
() => [ | () => [ | ||||
// { | |||||
// name: "action", | |||||
// label: t("Actions"), | |||||
// onClick: onStaffClick, | |||||
// buttonIcon: <EditNote />, | |||||
// }, | |||||
{ | |||||
name: "action", | |||||
label: t("Actions"), | |||||
onClick: onTeamClick, | |||||
buttonIcon: <EditNote />, | |||||
}, | |||||
{ name: "name", label: t("Name") }, | { name: "name", label: t("Name") }, | ||||
{ name: "code", label: t("Code") }, | { name: "code", label: t("Code") }, | ||||
{ name: "description", label: t("description") }, | { name: "description", label: t("description") }, | ||||