From faa9788e16badf95462e8286751b04f8ccc72e12 Mon Sep 17 00:00:00 2001 From: Akseli Kolari <33838340+Akzuu@users.noreply.github.com> Date: Sun, 19 Nov 2023 08:18:54 +0200 Subject: [PATCH] Feat/71 (#85) --- package-lock.json | 29 ++- package.json | 3 +- .../DivingCylinderSetList.tsx | 12 +- src/components/FillEvents/ListFillEvents.tsx | 105 ++++++----- src/components/common/Table.tsx | 166 ----------------- .../common/Table/CommonTable.module.scss | 80 ++++++++ src/components/common/Table/CommonTable.tsx | 176 ++++++++++++++++++ src/styles/commonTable/commonTable.css | 18 -- src/styles/commonTable/commonTable.sass | 22 --- src/variables.scss | 3 + 10 files changed, 355 insertions(+), 259 deletions(-) delete mode 100644 src/components/common/Table.tsx create mode 100644 src/components/common/Table/CommonTable.module.scss create mode 100644 src/components/common/Table/CommonTable.tsx delete mode 100644 src/styles/commonTable/commonTable.css delete mode 100644 src/styles/commonTable/commonTable.sass diff --git a/package-lock.json b/package-lock.json index 348a173..1589571 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "@types/react-dom": "^18.0.6", "axios": "^1.1.3", "bootstrap": "^5.2.1", + "date-fns": "^2.30.0", "formik": "^2.2.9", "google-libphonenumber": "^3.2.32", "react": "^18.2.0", @@ -1902,11 +1903,11 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz", - "integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", + "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", "dependencies": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" @@ -1924,6 +1925,11 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/runtime/node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, "node_modules/@babel/template": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", @@ -6514,6 +6520,21 @@ "node": ">=10" } }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", diff --git a/package.json b/package.json index cc038fa..445a4a4 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@types/react-dom": "^18.0.6", "axios": "^1.1.3", "bootstrap": "^5.2.1", + "date-fns": "^2.30.0", "formik": "^2.2.9", "google-libphonenumber": "^3.2.32", "react": "^18.2.0", @@ -64,11 +65,11 @@ "@typescript-eslint/eslint-plugin": "^5.36.2", "@typescript-eslint/parser": "^5.36.2", "eslint": "^8.23.0", - "eslint-plugin-react-hooks": "^4.6.0", "eslint-config-prettier": "^8.5.0", "eslint-config-standard-with-typescript": "^23.0.0", "eslint-plugin-n": "^15.3.0", "eslint-plugin-promise": "^6.1.0", + "eslint-plugin-react-hooks": "^4.6.0", "husky": "^8.0.1", "lint-staged": "^13.0.3", "prettier": "^2.7.1", diff --git a/src/components/DivingCylinderSet/DivingCylinderSetList.tsx b/src/components/DivingCylinderSet/DivingCylinderSetList.tsx index 313e36e..2fb1112 100644 --- a/src/components/DivingCylinderSet/DivingCylinderSetList.tsx +++ b/src/components/DivingCylinderSet/DivingCylinderSetList.tsx @@ -9,26 +9,36 @@ import { archiveDivingCylinderSet } from '../../lib/apiRequests/divingCylinderSe import { useDivingCylinderQuery } from '../../lib/queries/divingCylinderQuery'; import { DIVING_CYLINDER_SETS_QUERY_KEY } from '../../lib/queries/queryKeys'; import { getUserIdFromAccessToken } from '../../lib/utils'; -import { CommonTable, TableColumn, TableRow } from '../common/Table'; +import { + CommonTable, + TableColumn, + TableRow, +} from '../common/Table/CommonTable'; const DIVING_CYLINDER_SET_COLUMNS: TableColumn[] = [ { title: 'Nimi', + shortTitle: 'Nimi', }, { title: 'Koko (l)', + shortTitle: 'l', }, { title: 'Materiaali', + shortTitle: 'Mat', }, { title: 'Suurin täyttöpaine (bar)', + shortTitle: 'bar', }, { title: 'Sarjanumero', + shortTitle: 'SN', }, { title: 'Katsastusvuosi', + shortTitle: 'KV', }, ]; diff --git a/src/components/FillEvents/ListFillEvents.tsx b/src/components/FillEvents/ListFillEvents.tsx index b44b805..6fd7006 100644 --- a/src/components/FillEvents/ListFillEvents.tsx +++ b/src/components/FillEvents/ListFillEvents.tsx @@ -1,58 +1,69 @@ +import format from 'date-fns/format'; import { useFillEventQuery } from '../../lib/queries/FillEventQuery'; -import { FillEvent } from '../../interfaces/FillEvent'; import { formatEurCentsToEur } from '../../lib/utils'; +import { + CommonTable, + TableColumn, + TableRow, +} from '../common/Table/CommonTable'; +import { useMemo } from 'react'; -const FillEventRow = ({ - data, - index, -}: { - data: FillEvent; - index: number; -}): JSX.Element => { - return ( - - {data.createdAt} - {data.cylinderSetName} - {data.gasMixture} - {data.description} - {formatEurCentsToEur(data.price)} - - ); -}; +const FILL_EVENT_COLUMNS: TableColumn[] = [ + { + title: 'Päivämäärä', + shortTitle: 'Pvm', + }, + { + title: 'Pullosetti', + shortTitle: 'PS', + }, + { + title: 'Kaasuseos', + shortTitle: 'KS', + }, + { + title: 'Lisätiedot', + shortTitle: 'LT', + }, + { + title: 'Hinta (€)', + shortTitle: '€', + }, +]; -export const ListFillEvents = (): JSX.Element => { - const fillEvents: FillEvent[] = useFillEventQuery().data ?? []; +const dateFormatter = (date: string): string => + format(new Date(date), 'd.MM.yy'); +export const ListFillEvents = (): JSX.Element => { + const { data: fillEvents } = useFillEventQuery(); + const rows: TableRow[] = useMemo( + () => + fillEvents?.map((fillEvent) => ({ + id: fillEvent.id, + mainRow: [ + dateFormatter(fillEvent.createdAt), + fillEvent.cylinderSetName, + fillEvent.gasMixture, + fillEvent.description, + formatEurCentsToEur(fillEvent.price), + ], + })) ?? [], + [fillEvents] + ); return (
-
-

Täyttöhistoria

-
-

Täyttöjen hinta yhteensä

-

- {formatEurCentsToEur( - fillEvents.reduce((acc, fillEvent) => acc + fillEvent.price, 0) - )}{' '} - € -

-
+
+

Täyttöhistoria

+

+ Täyttöjen hinta yhteensä:{' '} + {formatEurCentsToEur( + fillEvents?.reduce((acc, fillEvent) => acc + fillEvent.price, 0) ?? + 0 + )}{' '} + € +

- - - - - - - - - - - - {fillEvents.map((fillEvent, index) => ( - - ))} - -
Päivämääräpullosettikaasuseoslisätiedothinta (€)
+
); }; diff --git a/src/components/common/Table.tsx b/src/components/common/Table.tsx deleted file mode 100644 index 0381913..0000000 --- a/src/components/common/Table.tsx +++ /dev/null @@ -1,166 +0,0 @@ -import React, { useCallback } from 'react'; -import { BsPencil, BsTrash } from 'react-icons/bs'; -import '../../styles/commonTable/commonTable.css'; -import { IconButton, IconButtonProps } from './Buttons'; - -type Row = Array; - -export type TableColumn = { - title: string; -}; - -export type TableRow = { - id: string; - mainRow: Row; - childRows?: Row[]; -}; - -type CommonTableProps = { - columns: TableColumn[]; - rows: TableRow[]; - includeRowNumber?: boolean; - includeEditButton?: boolean; - includeDeleteButton?: boolean; - onRowDelete?: (id: string) => void; -}; - -const IconButtonCell: React.FC = ({ - onClick, - icon, -}): JSX.Element => { - return ( - - - - ); -}; - -/** - * Common table element which can be used in a number of situations. - * HOX Row length MUST ALWAYS match the length of columns! Otherwise, - * the styling will break! Empty values can be indicated by using null - */ -export const CommonTable: React.FC = ({ - columns, - rows, - includeDeleteButton = false, - includeEditButton = false, - includeRowNumber = false, - onRowDelete, -}): JSX.Element => { - const handleEditButtonClick = useCallback(() => { - // TODO - }, []); - - const handleDeleteButtonClick = useCallback( - (id: string) => { - onRowDelete?.(id); - }, - [onRowDelete] - ); - - return ( - - - - {includeRowNumber ? ( - - ) : null} - {columns.map((column) => ( - - ))} - {includeEditButton ? ( - - ) : null} - {includeDeleteButton ? ( - - ) : null} - - - - {rows.map((row, index) => ( - - - {includeRowNumber ? ( - - ) : null} - - {row.mainRow.map((value, valueIndex) => ( - - ))} - - {includeEditButton ? ( - } - onClick={handleEditButtonClick} - /> - ) : null} - {includeDeleteButton ? ( - } - onClick={() => handleDeleteButtonClick(row.id)} - /> - ) : null} - - {/* Does the row have "child" rows */} - {row.childRows?.map((childRow, childRowIndex) => ( - - {includeRowNumber ? ( - - ) : null} - {childRow.map((value, valueIndex) => ( - - ))} - {includeEditButton ? ( - - ) : null} - {includeDeleteButton ? ( - - ) : null} - - ))} - - ))} - -
- # - - {column.title} - - Muokkaa - - Poista -
- {index + 1} - - {value} -
- {index + 1}.{childRowIndex + 1} - - {value} -
- ); -}; diff --git a/src/components/common/Table/CommonTable.module.scss b/src/components/common/Table/CommonTable.module.scss new file mode 100644 index 0000000..b96bcd8 --- /dev/null +++ b/src/components/common/Table/CommonTable.module.scss @@ -0,0 +1,80 @@ +@import '../../../variables.scss'; + +.noBackground:not(:hover) { + background-color: rgba(0, 0, 0, 0) !important; + border-color: rgba(0, 0, 0, 0) !important; +} + +.content { + box-sizing: border-box; + background: $white; + border-radius: 8px; + box-shadow: 0px 4px 10px 2px rgba(0, 0, 0, 0.1); + display: flex; + overflow: auto; + width: 100%; +} + +table { + width: 100%; + + thead { + background-color: $timberwolf; + } + + .evenRow { + background-color: $ghost-white; + } + + .oddRow { + background-color: $white; + } + + tr { + box-sizing: border-box; + } + + th { + padding: 0.5rem 1rem; + + span { + &:first-child { + display: inline; + } + &:last-child { + display: none; + } + } + } + + td { + border: 1px solid $timberwolf; + padding: 0 1rem; + } +} + +@media (max-width: 780px) { + h1 { + font-size: 1.5rem; + width: 50%; + } + h2 { + font-size: 1.25rem; + width: 50%; + } + + table { + th { + padding: 0.25rem 0.5rem; + + span { + &:first-child { + display: none; + } + &:last-child { + display: inline; + } + } + } + } +} diff --git a/src/components/common/Table/CommonTable.tsx b/src/components/common/Table/CommonTable.tsx new file mode 100644 index 0000000..8e71c5b --- /dev/null +++ b/src/components/common/Table/CommonTable.tsx @@ -0,0 +1,176 @@ +import React, { useCallback } from 'react'; +import { BsPencil, BsTrash } from 'react-icons/bs'; +import { IconButton, IconButtonProps } from '../Buttons'; +import styles from './CommonTable.module.scss'; + +type Row = Array; + +export type TableColumn = { + title: string; + shortTitle: string; +}; + +export type TableRow = { + id: string; + mainRow: Row; + childRows?: Row[]; + formatter?: () => string; +}; + +type CommonTableProps = { + columns: TableColumn[]; + rows: TableRow[]; + includeRowNumber?: boolean; + includeEditButton?: boolean; + includeDeleteButton?: boolean; + onRowDelete?: (id: string) => void; +}; + +const IconButtonCell: React.FC = ({ + onClick, + icon, +}): JSX.Element => { + return ( + + + + ); +}; + +/** + * Common table element which can be used in a number of situations. + * HOX Row length MUST ALWAYS match the length of columns! Otherwise, + * the styling will break! Empty values can be indicated by using null + */ +export const CommonTable: React.FC = ({ + columns, + rows, + includeDeleteButton = false, + includeEditButton = false, + includeRowNumber = false, + onRowDelete, +}): JSX.Element => { + const handleEditButtonClick = useCallback(() => { + // TODO + }, []); + + const handleDeleteButtonClick = useCallback( + (id: string) => { + onRowDelete?.(id); + }, + [onRowDelete] + ); + + return ( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions +
+ + + + {includeRowNumber ? ( + + ) : null} + {columns.map((column) => ( + + ))} + {includeEditButton ? ( + + ) : null} + {includeDeleteButton ? ( + + ) : null} + + + + {rows.map((row, index) => ( + + + {includeRowNumber ? ( + + ) : null} + + {row.mainRow.map((value, valueIndex) => ( + + ))} + + {includeEditButton ? ( + } + onClick={handleEditButtonClick} + /> + ) : null} + {includeDeleteButton ? ( + } + onClick={() => handleDeleteButtonClick(row.id)} + /> + ) : null} + + {/* Does the row have "child" rows */} + {row.childRows?.map((childRow, childRowIndex) => ( + + {includeRowNumber ? ( + + ) : null} + {childRow.map((value, valueIndex) => ( + + ))} + {includeEditButton ? ( + + ) : null} + {includeDeleteButton ? ( + + ) : null} + + ))} + + ))} + +
+ # + + {column.title} + {column.shortTitle} + + Muokkaa + + Poista +
+ {index + 1} + + {value} +
+ {index + 1}.{childRowIndex + 1} + + {value} +
+
+ ); +}; diff --git a/src/styles/commonTable/commonTable.css b/src/styles/commonTable/commonTable.css deleted file mode 100644 index 4c726d3..0000000 --- a/src/styles/commonTable/commonTable.css +++ /dev/null @@ -1,18 +0,0 @@ -.no-background:not(:hover) { - background-color: rgba(0, 0, 0, 0) !important; - border-color: rgba(0, 0, 0, 0) !important; -} - -.table { - border: 1px solid #D6D6D6; - white-space: nowrap; -} -.table .tableHead { - background-color: #D9E1E9; -} -.table .evenRow { - background-color: rgba(217, 225, 233, 0.2784313725); -} -.table .oddRow { - background-color: #FFFFFF; -} diff --git a/src/styles/commonTable/commonTable.sass b/src/styles/commonTable/commonTable.sass deleted file mode 100644 index 2c3f4ab..0000000 --- a/src/styles/commonTable/commonTable.sass +++ /dev/null @@ -1,22 +0,0 @@ -$transparentColor: rgba(0, 0, 0, 0) -$evenRow: #D9E1E947 -$oddRow: #FFFFFF -$titleBarBlue: #D9E1E9 -$borderColor: #D6D6D6 - -.no-background:not(:hover) - background-color: $transparentColor !important - border-color: $transparentColor !important - -.table - border: 1px solid $borderColor - white-space: nowrap - - .tableHead - background-color: $titleBarBlue - - .evenRow - background-color: $evenRow - - .oddRow - background-color: $oddRow diff --git a/src/variables.scss b/src/variables.scss index 50f041e..8f8a063 100644 --- a/src/variables.scss +++ b/src/variables.scss @@ -1,3 +1,4 @@ +$aluminium: #d6d6d6; $black: #000000; $blue-charcoal: #1b2631; $dark-blue: #003143; @@ -6,3 +7,5 @@ $blue-hover: #405c7a; $grey: #c3c3c3; $white: #ffffff; $white-smoke: #f4f4f4; +$ghost-white: #d9e1e947; +$timberwolf: #d9e1e9;