From 16502018cb0d4f3a91b60d53a9473d1dde845a74 Mon Sep 17 00:00:00 2001 From: nicoleamber Date: Tue, 12 Sep 2023 14:53:51 +0800 Subject: [PATCH] [M1_TR-212] Refactored structure --- web/src/app/job/context.ts | 4 ++ web/src/app/job/hooks.ts | 22 ++++++ web/src/app/job/page.tsx | 40 +++++++++++ .../{Pagination.tsx => Pagination/index.tsx} | 13 ++-- web/src/components/atoms/StatusChip.tsx | 30 -------- web/src/components/atoms/StatusChip/index.tsx | 17 +++++ .../molecules/CreatedDateRangeFilter/hooks.ts | 22 ++++++ .../index.tsx} | 17 ++--- .../molecules/EstimationStatusFilter.tsx | 50 -------------- .../molecules/EstimationStatusFilter/hooks.ts | 15 ++++ .../EstimationStatusFilter/index.tsx | 33 +++++++++ .../components/molecules/SearchBar/hooks.ts | 15 ++++ .../{SearchBar.tsx => SearchBar/index.tsx} | 10 +-- web/src/components/molecules/TagFilter.tsx | 48 ------------- .../components/molecules/TagFilter/hooks.ts | 15 ++++ .../components/molecules/TagFilter/index.tsx | 33 +++++++++ .../index.tsx} | 20 +++--- .../organisms/SearchFilterHeader/hooks.ts | 14 ++++ .../index.tsx} | 18 ++--- web/{ => src}/styles/Filter.module.css | 0 web/src/utils/constants/estimationStatus.ts | 7 ++ .../constants/jobTableData.ts} | 69 +------------------ web/src/utils/constants/statusChipColor.ts | 11 +++ web/src/utils/constants/tags.ts | 5 ++ web/src/utils/types/job.ts | 28 ++++++++ 25 files changed, 311 insertions(+), 245 deletions(-) create mode 100644 web/src/app/job/context.ts create mode 100644 web/src/app/job/hooks.ts create mode 100644 web/src/app/job/page.tsx rename web/src/components/atoms/{Pagination.tsx => Pagination/index.tsx} (62%) delete mode 100644 web/src/components/atoms/StatusChip.tsx create mode 100644 web/src/components/atoms/StatusChip/index.tsx create mode 100644 web/src/components/molecules/CreatedDateRangeFilter/hooks.ts rename web/src/components/molecules/{CreatedDateRangeFilter.tsx => CreatedDateRangeFilter/index.tsx} (73%) delete mode 100644 web/src/components/molecules/EstimationStatusFilter.tsx create mode 100644 web/src/components/molecules/EstimationStatusFilter/hooks.ts create mode 100644 web/src/components/molecules/EstimationStatusFilter/index.tsx create mode 100644 web/src/components/molecules/SearchBar/hooks.ts rename web/src/components/molecules/{SearchBar.tsx => SearchBar/index.tsx} (73%) delete mode 100644 web/src/components/molecules/TagFilter.tsx create mode 100644 web/src/components/molecules/TagFilter/hooks.ts create mode 100644 web/src/components/molecules/TagFilter/index.tsx rename web/src/components/organisms/{JobListTable.tsx => JobListTable/index.tsx} (86%) create mode 100644 web/src/components/organisms/SearchFilterHeader/hooks.ts rename web/src/components/organisms/{SearchFilterHeader.tsx => SearchFilterHeader/index.tsx} (74%) rename web/{ => src}/styles/Filter.module.css (100%) create mode 100644 web/src/utils/constants/estimationStatus.ts rename web/src/{app/page.tsx => utils/constants/jobTableData.ts} (77%) create mode 100644 web/src/utils/constants/statusChipColor.ts create mode 100644 web/src/utils/constants/tags.ts create mode 100644 web/src/utils/types/job.ts diff --git a/web/src/app/job/context.ts b/web/src/app/job/context.ts new file mode 100644 index 0000000..cc54b7d --- /dev/null +++ b/web/src/app/job/context.ts @@ -0,0 +1,4 @@ +import { JobTable } from '@/utils/types/job'; +import { createContext } from 'react'; + +export const JobListContext = createContext(undefined); diff --git a/web/src/app/job/hooks.ts b/web/src/app/job/hooks.ts new file mode 100644 index 0000000..3d559dd --- /dev/null +++ b/web/src/app/job/hooks.ts @@ -0,0 +1,22 @@ +import { JobTable } from '@/utils/types/job'; +import { useContext, useState } from 'react'; +import { JobListContext } from './context'; + +export const useJobListContext = (): JobTable => { + const jobs = useContext(JobListContext); + + if (jobs === undefined) { + throw new Error('Missing JobListContext'); + } + + return jobs; +}; + +export const useHooks = () => { + const [page, setPage] = useState(1); + + return { + page, + setPage + }; +}; diff --git a/web/src/app/job/page.tsx b/web/src/app/job/page.tsx new file mode 100644 index 0000000..f6f5116 --- /dev/null +++ b/web/src/app/job/page.tsx @@ -0,0 +1,40 @@ +'use client'; + +import Pagination from '@/components/atoms/Pagination'; +import JobListTable from '@/components/organisms/JobListTable'; +import SearchFilterHeader from '@/components/organisms/SearchFilterHeader'; +import { JobColumns, JobData } from '@/utils/constants/jobTableData'; +import { Grid } from '@mui/material'; +import { JobListContext } from './context'; +import { useHooks } from './hooks'; + +const JobList = (): JSX.Element => { + const { page, setPage } = useHooks(); + + return ( +
+ + + + + + + + + + + + + +
+ ); +}; + +export default JobList; diff --git a/web/src/components/atoms/Pagination.tsx b/web/src/components/atoms/Pagination/index.tsx similarity index 62% rename from web/src/components/atoms/Pagination.tsx rename to web/src/components/atoms/Pagination/index.tsx index b2e416e..ec8c7c8 100644 --- a/web/src/components/atoms/Pagination.tsx +++ b/web/src/components/atoms/Pagination/index.tsx @@ -7,20 +7,15 @@ interface Props { onChange: (page: number) => void; } -const Pagination: FC = ({ count = 12, page = 1, onChange }: Props) => { - const handlePageChange = ( - event: React.ChangeEvent, - newPage: number - ) => { - onChange(newPage); - }; - +const Pagination: FC = ({ count, page, onChange }: Props) => { return ( , newPage: number) => + onChange(newPage) + } color='primary' shape='rounded' showFirstButton diff --git a/web/src/components/atoms/StatusChip.tsx b/web/src/components/atoms/StatusChip.tsx deleted file mode 100644 index 6a9a512..0000000 --- a/web/src/components/atoms/StatusChip.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { Chip } from '@mui/material'; -import { FC } from 'react'; - -interface Props { - label: string; -} - -const colors: Record = { - 'Not yet Created': '#FFB4AF', - Making: '#FDFF8F', - Approved: '#8AFFB2', - 'Sent to Customer': '#84C1FF', - Closed: '#65707b33' -}; - -const StatusChip: FC = ({ label }) => { - const color = colors[label] || '#65707b33'; - - return ( - - ); -}; - -export default StatusChip; diff --git a/web/src/components/atoms/StatusChip/index.tsx b/web/src/components/atoms/StatusChip/index.tsx new file mode 100644 index 0000000..c031708 --- /dev/null +++ b/web/src/components/atoms/StatusChip/index.tsx @@ -0,0 +1,17 @@ +import { ChipColors } from '@/utils/constants/statusChipColor'; +import { Chip, ChipProps } from '@mui/material'; +import { FC } from 'react'; + +const StatusChip: FC = ({ label }: ChipProps) => { + return ( + + ); +}; + +export default StatusChip; diff --git a/web/src/components/molecules/CreatedDateRangeFilter/hooks.ts b/web/src/components/molecules/CreatedDateRangeFilter/hooks.ts new file mode 100644 index 0000000..fd3c385 --- /dev/null +++ b/web/src/components/molecules/CreatedDateRangeFilter/hooks.ts @@ -0,0 +1,22 @@ +import { Moment } from 'moment'; +import { useState } from 'react'; + +export const useHooks = () => { + const [startDate, setStartDate] = useState(); + const [endDate, setEndDate] = useState(); + + const handleStartDateChange = (date: Moment | null): void => { + setStartDate(date); + }; + + const handleEndDateChange = (date: Moment | null): void => { + setEndDate(date); + }; + + return { + startDate, + handleStartDateChange, + endDate, + handleEndDateChange + }; +}; diff --git a/web/src/components/molecules/CreatedDateRangeFilter.tsx b/web/src/components/molecules/CreatedDateRangeFilter/index.tsx similarity index 73% rename from web/src/components/molecules/CreatedDateRangeFilter.tsx rename to web/src/components/molecules/CreatedDateRangeFilter/index.tsx index a75ccab..abfc4b8 100644 --- a/web/src/components/molecules/CreatedDateRangeFilter.tsx +++ b/web/src/components/molecules/CreatedDateRangeFilter/index.tsx @@ -1,24 +1,15 @@ 'use-client'; +import styles from '@/styles/Filter.module.css'; import { Box } from '@mui/material'; import { DatePicker } from '@mui/x-date-pickers'; import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; -import { Moment } from 'moment'; -import { useState } from 'react'; -import styles from 'styles/Filter.module.css'; +import { useHooks } from './hooks'; const CreateDateRangeFilter = () => { - const [startDate, setStartDate] = useState(); - const [endDate, setEndDate] = useState(); - - const handleStartDateChange = (date: Moment | null): void => { - setStartDate(date); - }; - - const handleEndDateChange = (date: Moment | null): void => { - setEndDate(date); - }; + const { startDate, handleStartDateChange, endDate, handleEndDateChange } = + useHooks(); return ( diff --git a/web/src/components/molecules/EstimationStatusFilter.tsx b/web/src/components/molecules/EstimationStatusFilter.tsx deleted file mode 100644 index 210d6fe..0000000 --- a/web/src/components/molecules/EstimationStatusFilter.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { - FormControl, - InputLabel, - MenuItem, - Select, - SelectChangeEvent -} from '@mui/material'; -import { useState } from 'react'; -import styles from 'styles/Filter.module.css'; - -const estimationStatus = [ - { id: 1, status: 'Not yet Created' }, - { id: 2, status: 'Making' }, - { id: 3, status: 'Approved' }, - { id: 4, status: 'Sent to Customer' }, - { id: 5, status: 'Closed' } -]; - -const EstimationStatusFilter = () => { - const [status, setStatus] = useState(''); - - const handleStatusChange = (e: SelectChangeEvent) => { - setStatus(e.target.value); - }; - - return ( - - - Estimation Status - - - - ); -}; - -export default EstimationStatusFilter; diff --git a/web/src/components/molecules/EstimationStatusFilter/hooks.ts b/web/src/components/molecules/EstimationStatusFilter/hooks.ts new file mode 100644 index 0000000..9c1499c --- /dev/null +++ b/web/src/components/molecules/EstimationStatusFilter/hooks.ts @@ -0,0 +1,15 @@ +import { SelectChangeEvent } from '@mui/material'; +import { useState } from 'react'; + +export const useHooks = () => { + const [status, setStatus] = useState(''); + + const handleChange = (e: SelectChangeEvent) => { + setStatus(e.target.value); + }; + + return { + status, + handleChange + }; +}; diff --git a/web/src/components/molecules/EstimationStatusFilter/index.tsx b/web/src/components/molecules/EstimationStatusFilter/index.tsx new file mode 100644 index 0000000..99188dc --- /dev/null +++ b/web/src/components/molecules/EstimationStatusFilter/index.tsx @@ -0,0 +1,33 @@ +import styles from '@/styles/Filter.module.css'; +import { EstimationStatus } from '@/utils/constants/estimationStatus'; +import { FormControl, InputLabel, MenuItem, Select } from '@mui/material'; +import { useHooks } from './hooks'; + +const EstimationStatusFilter = () => { + const { status, handleChange } = useHooks(); + + return ( + + + Estimation Status + + + + ); +}; + +export default EstimationStatusFilter; diff --git a/web/src/components/molecules/SearchBar/hooks.ts b/web/src/components/molecules/SearchBar/hooks.ts new file mode 100644 index 0000000..ab13b6d --- /dev/null +++ b/web/src/components/molecules/SearchBar/hooks.ts @@ -0,0 +1,15 @@ +import { ChangeEvent, useState } from 'react'; + +export const useHooks = () => { + const [searchKeyword, setSearchKeyword] = useState(''); + + const handleSearch = (e: ChangeEvent) => { + setSearchKeyword(e.target.value); + }; + + return { + searchKeyword, + handleSearch + }; + +}; diff --git a/web/src/components/molecules/SearchBar.tsx b/web/src/components/molecules/SearchBar/index.tsx similarity index 73% rename from web/src/components/molecules/SearchBar.tsx rename to web/src/components/molecules/SearchBar/index.tsx index 701fe41..83af8f4 100644 --- a/web/src/components/molecules/SearchBar.tsx +++ b/web/src/components/molecules/SearchBar/index.tsx @@ -1,3 +1,4 @@ +import styles from '@/styles/Filter.module.css'; import SearchIcon from '@mui/icons-material/Search'; import { FormControl, @@ -5,15 +6,10 @@ import { InputLabel, OutlinedInput } from '@mui/material'; -import { useState } from 'react'; -import styles from 'styles/Filter.module.css'; +import { useHooks } from './hooks'; const SearchBar = () => { - const [searchKeyword, setSearchKeyword] = useState(''); - - const handleSearch = (e: React.ChangeEvent) => { - setSearchKeyword(e.target.value); - }; + const { searchKeyword, handleSearch } = useHooks(); return ( diff --git a/web/src/components/molecules/TagFilter.tsx b/web/src/components/molecules/TagFilter.tsx deleted file mode 100644 index ea603bc..0000000 --- a/web/src/components/molecules/TagFilter.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { - FormControl, - InputLabel, - MenuItem, - Select, - SelectChangeEvent -} from '@mui/material'; -import { useState } from 'react'; -import styles from 'styles/Filter.module.css'; - -const tags = [ - { id: 1, value: 'TAG_A', name: 'Tag A' }, - { id: 2, value: 'TAG_B', name: 'Tag B' }, - { id: 3, value: 'TAG_C', name: 'Tag C' } -]; - -const TagFilter = () => { - const [tag, setTag] = useState(''); - - const handleTagChange = (e: SelectChangeEvent) => { - setTag(e.target.value); - }; - - return ( - - - Tag - - - - ); -}; - -export default TagFilter; diff --git a/web/src/components/molecules/TagFilter/hooks.ts b/web/src/components/molecules/TagFilter/hooks.ts new file mode 100644 index 0000000..e835a95 --- /dev/null +++ b/web/src/components/molecules/TagFilter/hooks.ts @@ -0,0 +1,15 @@ +import { SelectChangeEvent } from '@mui/material'; +import { useState } from 'react'; + +export const useHooks = () => { + const [tag, setTag] = useState(''); + + const handleChange = (e: SelectChangeEvent) => { + setTag(e.target.value); + }; + + return { + tag, + handleChange + }; +}; diff --git a/web/src/components/molecules/TagFilter/index.tsx b/web/src/components/molecules/TagFilter/index.tsx new file mode 100644 index 0000000..d12fed7 --- /dev/null +++ b/web/src/components/molecules/TagFilter/index.tsx @@ -0,0 +1,33 @@ +import styles from '@/styles/Filter.module.css'; +import { Tags } from '@/utils/constants/tags'; +import { FormControl, InputLabel, MenuItem, Select } from '@mui/material'; +import { useHooks } from './hooks'; + +const TagFilter = () => { + const { tag, handleChange } = useHooks(); + + return ( + + + Tag + + + + ); +}; + +export default TagFilter; diff --git a/web/src/components/organisms/JobListTable.tsx b/web/src/components/organisms/JobListTable/index.tsx similarity index 86% rename from web/src/components/organisms/JobListTable.tsx rename to web/src/components/organisms/JobListTable/index.tsx index d301622..2af535b 100644 --- a/web/src/components/organisms/JobListTable.tsx +++ b/web/src/components/organisms/JobListTable/index.tsx @@ -1,6 +1,8 @@ /* eslint-disable no-mixed-spaces-and-tabs */ -import { Column, JobData } from '@/app/page'; +import { useJobListContext } from '@/app/job/hooks'; import StatusChip from '@/components/atoms/StatusChip'; +import { TableColumn } from '@/utils/constants/jobTableData'; +import { JobTableRow } from '@/utils/types/job'; import { Box, Paper, @@ -13,17 +15,13 @@ import { TableRow, Typography } from '@mui/material'; -import { FC } from 'react'; -interface Props { - columns: Column[]; - data: JobData[]; -} +const JobListTable = (): JSX.Element => { + const { columns, data } = useJobListContext(); -const JobListTable: FC = ({ columns, data }: Props) => { const renderTableCellContent = ( - column: Column, - row: JobData + column: TableColumn, + row: JobTableRow ): JSX.Element => { switch (column.key) { case 'tags': @@ -99,10 +97,10 @@ const JobListTable: FC = ({ columns, data }: Props) => { - {data.map((row: JobData) => ( + {data.map((row: JobTableRow) => ( {columns.map( - (column: Column, index) => ( + (column: TableColumn, index) => ( {renderTableCellContent( column, diff --git a/web/src/components/organisms/SearchFilterHeader/hooks.ts b/web/src/components/organisms/SearchFilterHeader/hooks.ts new file mode 100644 index 0000000..bfad85f --- /dev/null +++ b/web/src/components/organisms/SearchFilterHeader/hooks.ts @@ -0,0 +1,14 @@ +import { useState } from 'react'; + +export const useHooks = () => { + const [isExpanded, setIsExpanded] = useState(false); + + const toggleFilters = () => { + setIsExpanded(!isExpanded); + }; + + return { + isExpanded, + toggleFilters + }; +}; diff --git a/web/src/components/organisms/SearchFilterHeader.tsx b/web/src/components/organisms/SearchFilterHeader/index.tsx similarity index 74% rename from web/src/components/organisms/SearchFilterHeader.tsx rename to web/src/components/organisms/SearchFilterHeader/index.tsx index 772cd20..0b4b406 100644 --- a/web/src/components/organisms/SearchFilterHeader.tsx +++ b/web/src/components/organisms/SearchFilterHeader/index.tsx @@ -2,21 +2,17 @@ import { FilterCog } from '@/assets/icons/FilterCog'; import { FilterRemove } from '@/assets/icons/FilterRemove'; +import styles from '@/styles/Filter.module.css'; import TableRows from '@mui/icons-material/TableRows'; import { Box, Button, Collapse } from '@mui/material'; -import { useState } from 'react'; -import styles from 'styles/Filter.module.css'; -import CreateDateRangeFilter from '../molecules/CreatedDateRangeFilter'; -import EstimationStatusFilter from '../molecules/EstimationStatusFilter'; -import SearchBar from '../molecules/SearchBar'; -import TagFilter from '../molecules/TagFilter'; +import CreateDateRangeFilter from '../../molecules/CreatedDateRangeFilter'; +import EstimationStatusFilter from '../../molecules/EstimationStatusFilter'; +import SearchBar from '../../molecules/SearchBar'; +import TagFilter from '../../molecules/TagFilter'; +import { useHooks } from './hooks'; const SearchFilterHeader = (): JSX.Element => { - const [isExpanded, setIsExpanded] = useState(false); - - const toggleFilters = () => { - setIsExpanded(!isExpanded); - }; + const { isExpanded, toggleFilters } = useHooks(); return ( ; - schedules: Array; - estimation: Estimation; - personInCharge: string; - pipelinePhase: string; - createdAt: string; - [key: string]: string | number | string[] | Estimation; -} - -const columns: Column[] = [ +export const JobColumns : TableColumn[] = [ { key: 'title', label: 'Job Title', width: 200 }, { key: 'customer', label: 'Customer Name', width: 170 }, { key: 'tags', label: 'Tags', width: 160 }, @@ -42,40 +12,7 @@ const columns: Column[] = [ { key: 'createdAt', label: 'Created At', width: 120 } ]; -export default function JobList() { - const [page, setPage] = useState(1); - - const handlePageChange = (value: number) => { - setPage(value); - }; - return ( -
- - - - - - - - - - - -
- ); -} - -const data: JobData[] = [ +export const JobData: JobTableRow[] = [ { id: 1, title: 'New Summit', diff --git a/web/src/utils/constants/statusChipColor.ts b/web/src/utils/constants/statusChipColor.ts new file mode 100644 index 0000000..0f15dd6 --- /dev/null +++ b/web/src/utils/constants/statusChipColor.ts @@ -0,0 +1,11 @@ +export interface ChipProps { + label: string; +} + +export const ChipColors: Record = { + 'Not yet Created': '#FFB4AF', + Making: '#FDFF8F', + Approved: '#8AFFB2', + 'Sent to Customer': '#84C1FF', + Closed: '#65707b33' +}; diff --git a/web/src/utils/constants/tags.ts b/web/src/utils/constants/tags.ts new file mode 100644 index 0000000..f021459 --- /dev/null +++ b/web/src/utils/constants/tags.ts @@ -0,0 +1,5 @@ +export const Tags = [ + { id: 1, value: 'TAG_A', name: 'Tag A' }, + { id: 2, value: 'TAG_B', name: 'Tag B' }, + { id: 3, value: 'TAG_C', name: 'Tag C' } +]; diff --git a/web/src/utils/types/job.ts b/web/src/utils/types/job.ts new file mode 100644 index 0000000..816ad2d --- /dev/null +++ b/web/src/utils/types/job.ts @@ -0,0 +1,28 @@ +export interface TableColumn { + key: string; + label: string; + width?: number; +} + +export interface EstimationType { + status: string; + cost: number; +} + +export interface JobTableRow { + id: number; + title: string; + customer: string; + tags: Array; + schedules: Array; + estimation: EstimationType; + personInCharge: string; + pipelinePhase: string; + createdAt: string; + [key: string]: string | number | string[] | EstimationType; +} + +export interface JobTable { + columns: TableColumn[]; + data: JobTableRow[]; +}