2. fallback search resulr from column sorting feature updates 3. Add selected project display in Project cash flow pagedevelop
@@ -95,10 +95,10 @@ const MailSetting: React.FC<Props> = ({ | |||
try { | |||
// msg = "testEveryone" | |||
// await testEveryone() | |||
msg = "test7th" | |||
await test7th() | |||
// msg = "test15th" | |||
// await test15th() | |||
// msg = "test7th" | |||
// await test7th() | |||
msg = "test15th" | |||
await test15th() | |||
} catch (error) { | |||
console.log(error) | |||
console.log(msg) | |||
@@ -5,7 +5,7 @@ import { useState, useEffect, useMemo } from "react"; | |||
import Paper from "@mui/material/Paper"; | |||
import { TFunction } from "i18next"; | |||
import { useTranslation } from "react-i18next"; | |||
import { Card, CardHeader } from "@mui/material"; | |||
import { Card, CardContent, CardHeader } from "@mui/material"; | |||
import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; | |||
import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; | |||
import ReactApexChart from "react-apexcharts"; | |||
@@ -26,6 +26,7 @@ import dayjs from 'dayjs'; | |||
import ProjectTotalFee from "../CreateInvoice_forGen/ProjectTotalFee"; | |||
import Typography from "@mui/material/Typography"; | |||
import { useSearchParams } from 'next/navigation'; | |||
import { ResetTvOutlined } from "@mui/icons-material"; | |||
interface Props { | |||
projects: CashFlow[]; | |||
@@ -64,6 +65,7 @@ const ProjectCashFlow: React.FC = () => { | |||
const [monthlyAnticipateExpenditureList, setMonthlyAnticipateExpenditureList]: any[] = React.useState([0,0,0,0,0,0,0,0,0,0,0,0]); | |||
const [ledgerData, setLedgerData]: any[] = React.useState([]); | |||
const [isInitializing, setIsInitializing] = useState(true); | |||
const [projectInfo, setProjectInfo]: any[] = useState([]) | |||
const [cashFlowYear, setCashFlowYear]: any[] = React.useState( | |||
todayDate.getFullYear(), | |||
); | |||
@@ -86,6 +88,11 @@ const ProjectCashFlow: React.FC = () => { | |||
); | |||
const projectIdList = selectedRowsData.map((row: any) => row.id); | |||
setSelectedProjectIdList(projectIdList); | |||
console.log(projectData) | |||
setProjectInfo(projectData.filter((result:any)=> { | |||
// console.log("Checking ID:", result.id, "against list:", projectIdList); | |||
return projectIdList.includes(result.id) | |||
})) | |||
} | |||
}; | |||
@@ -240,7 +247,6 @@ const ProjectCashFlow: React.FC = () => { | |||
fetchReceivableAndExpenditureData(); | |||
fetchAnticipateData(); | |||
fetchProjectCashFlowLedger(); | |||
}, [cashFlowYear,selectedProjectIdList]); | |||
useEffect(() => { | |||
@@ -829,6 +835,15 @@ const ProjectCashFlow: React.FC = () => { | |||
onRowSelectionModelChange={handleSelectionChange} | |||
rowSelectionModel={selectionModel} | |||
/> | |||
<Grid container> | |||
<Grid item xs={12} md={12} lg={12}> | |||
<Card> | |||
<CardContent> | |||
{ projectInfo[0]?.projectCode && `${projectInfo[0]?.projectCode} - ${projectInfo[0]?.projectName}`} | |||
</CardContent> | |||
</Card> | |||
</Grid> | |||
</Grid> | |||
<Grid item sm> | |||
<div style={{ display: "inline-block", width: "50%" }}> | |||
<Grid item xs={12} md={12} lg={12}> | |||
@@ -28,7 +28,10 @@ const ProjectSearchWrapper: React.FC & SubComponents = async () => { | |||
let filteredProjects = projects; | |||
if (!isViewAllProjectRight) { | |||
filteredProjects = projects.filter((project) => project.teamId === teamId || project.team === "ST"); | |||
filteredProjects = projects.filter((project) => project.teamId === teamId ); | |||
if (teamId == 1){ | |||
filteredProjects = projects.filter((project) => project.teamId === teamId || project.team === "ST"); | |||
} | |||
} | |||
return ( | |||
@@ -158,50 +158,50 @@ function SearchResults<T extends ResultWithId>({ | |||
return column.underline ?? "always"; | |||
}; | |||
type OrderProps = Record<keyof T, Boolean> | |||
const [sortedItems, setSortedItems] = useState(items) | |||
const [orderProps, setOrderProps] = useState<OrderProps>(() => { | |||
if (items.length === 0) { | |||
return {} as OrderProps | |||
} | |||
return Object.keys(sortedItems[0]).reduce((acc, key) => { | |||
if (key === "deleted" || key === "id") return acc | |||
acc[key as keyof T] = false; | |||
return acc; | |||
}, {} as OrderProps); | |||
}); | |||
const changeOrder = useCallback((key: keyof T) => { | |||
// preserve all column sorting | |||
// setOrderProps( | |||
// (prev) => ({ | |||
// [...prev]: false, | |||
// [key]: !prev[key] | |||
// }) | |||
// ) | |||
// only sort 1 column | |||
setOrderProps( | |||
(prev) => { | |||
const newOrderProps = Object.keys(prev).reduce((acc, currKey) => { | |||
acc[currKey as keyof T] = currKey === key ? !prev[currKey as keyof T] : false; | |||
return acc; | |||
}, {} as OrderProps); | |||
return newOrderProps; | |||
} | |||
) | |||
}, []) | |||
const sortingItems = useCallback( | |||
(key: keyof T) => { | |||
// true === asc | |||
// false === desc | |||
console.log(orderProps) | |||
if (orderProps[key]) { | |||
return orderBy(sortedItems, key, 'asc') | |||
} else { | |||
return orderBy(sortedItems, key, 'desc') | |||
} | |||
} | |||
, [sortedItems, orderProps] | |||
) | |||
// type OrderProps = Record<keyof T, Boolean> | |||
// const [sortedItems, setSortedItems] = useState(items) | |||
// const [orderProps, setOrderProps] = useState<OrderProps>(() => { | |||
// if (items.length === 0) { | |||
// return {} as OrderProps | |||
// } | |||
// return Object.keys(sortedItems[0]).reduce((acc, key) => { | |||
// if (key === "deleted" || key === "id") return acc | |||
// acc[key as keyof T] = false; | |||
// return acc; | |||
// }, {} as OrderProps); | |||
// }); | |||
// const changeOrder = useCallback((key: keyof T) => { | |||
// // preserve all column sorting | |||
// // setOrderProps( | |||
// // (prev) => ({ | |||
// // [...prev]: false, | |||
// // [key]: !prev[key] | |||
// // }) | |||
// // ) | |||
// // only sort 1 column | |||
// setOrderProps( | |||
// (prev) => { | |||
// const newOrderProps = Object.keys(prev).reduce((acc, currKey) => { | |||
// acc[currKey as keyof T] = currKey === key ? !prev[currKey as keyof T] : false; | |||
// return acc; | |||
// }, {} as OrderProps); | |||
// return newOrderProps; | |||
// } | |||
// ) | |||
// }, []) | |||
// const sortingItems = useCallback( | |||
// (key: keyof T) => { | |||
// // true === asc | |||
// // false === desc | |||
// console.log(orderProps) | |||
// if (orderProps[key]) { | |||
// return orderBy(sortedItems, key, 'asc') | |||
// } else { | |||
// return orderBy(sortedItems, key, 'desc') | |||
// } | |||
// } | |||
// , [sortedItems, orderProps] | |||
// ) | |||
const table = ( | |||
<> | |||
<TableContainer sx={{ maxHeight: 440 }}> | |||
@@ -209,25 +209,15 @@ function SearchResults<T extends ResultWithId>({ | |||
<TableHead> | |||
<TableRow> | |||
{columns.filter(item => item.isHidden !== true).map((column, idx) => ( | |||
<TableCell | |||
key={`${column.name.toString()}${idx}`} | |||
onClick={() => { | |||
changeOrder(column.name) | |||
setSortedItems(sortingItems(column.name)) | |||
}} | |||
> | |||
<TableCell key={`${column.name.toString()}${idx}`}> | |||
{column?.type === "money" ? <div style={{display: "flex", justifyContent: "flex-end"}}>{column.label}</div> : column.label} | |||
{(() => { | |||
const isAscending = orderProps[column.name]; | |||
if (isAscending === undefined) return undefined; | |||
return isAscending ? <ArrowUp /> : <ArrowDown />; | |||
})()} | |||
</TableCell> | |||
))} | |||
</TableRow> | |||
</TableHead> | |||
<TableBody> | |||
{sortedItems | |||
{items | |||
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) | |||
.map((item) => { | |||
return ( | |||
@@ -280,7 +270,7 @@ function SearchResults<T extends ResultWithId>({ | |||
<TablePagination | |||
rowsPerPageOptions={[10, 25, 100]} | |||
component="div" | |||
count={sortedItems.length} | |||
count={items.length} | |||
rowsPerPage={rowsPerPage} | |||
page={page} | |||
onPageChange={handleChangePage} | |||
@@ -25,6 +25,7 @@ interface CommonProps { | |||
referenceDay: Dayjs; | |||
includeLeaves?: boolean; | |||
leaveTypes?: LeaveType[]; | |||
isTimesheetAdmendment?: boolean; | |||
} | |||
interface SingleAutocompleteProps extends CommonProps { | |||
@@ -44,7 +45,8 @@ interface MultiAutocompleteProps extends CommonProps { | |||
includeLeaves: false; | |||
} | |||
type Props = SingleAutocompleteProps | MultiAutocompleteProps; | |||
type Props = SingleAutocompleteProps | MultiAutocompleteProps ; | |||
const getGroupName = (t: TFunction, groupName: string): string => { | |||
switch (groupName) { | |||
@@ -73,6 +75,7 @@ const AutocompleteProjectSelect: React.FC<Props> = ({ | |||
multiple, | |||
leaveTypes, | |||
includeLeaves, | |||
isTimesheetAdmendment | |||
}) => { | |||
const { t } = useTranslation("home"); | |||
const allFilteredProjects = useMemo(() => { | |||
@@ -97,18 +100,20 @@ console.log(assignedProjects) | |||
label: `${p.code} - ${p.name}`, | |||
group: "assigned", | |||
})), | |||
// ...(includeLeaves && leaveTypes | |||
// ? leaveTypes.map((l) => ({ | |||
// value: `leave-${l.id}`, | |||
// label: t(l.name), | |||
// group: "leaves", | |||
// })) | |||
// : []), | |||
// ...nonAssignedProjects.map((p) => ({ | |||
// value: p.id, | |||
// label: `${p.code} - ${p.name}`, | |||
// group: assignedProjects.length === 0 ? "all-projects" : "non-assigned", | |||
// })), | |||
...(includeLeaves && leaveTypes | |||
? leaveTypes.map((l) => ({ | |||
value: `leave-${l.id}`, | |||
label: t(l.name), | |||
group: "leaves", | |||
})) | |||
: []), | |||
...(isTimesheetAdmendment | |||
? nonAssignedProjects.map((p) => ({ | |||
value: p.id, | |||
label: `${p.code} - ${p.name}`, | |||
group: assignedProjects.length === 0 ? "all-projects" : "non-assigned", | |||
})) | |||
: []), | |||
]; | |||
}, [assignedProjects, includeLeaves, leaveTypes, nonAssignedProjects, t]); | |||
@@ -177,6 +177,7 @@ const TimesheetEditModal: React.FC<Props> = ({ | |||
setValue("taskGroupId", firstTaskGroup?.value); | |||
setValue("taskId", undefined); | |||
}} | |||
isTimesheetAdmendment={true} | |||
/> | |||
)} | |||
rules={{ deps: ["taskGroupId", "taskId"] }} | |||