From 642f2ab3f5e5d5d36fa55af7c2ebe7511ad39716 Mon Sep 17 00:00:00 2001 From: zukki30 Date: Thu, 26 May 2022 03:39:30 +0900 Subject: [PATCH 1/9] fix: Fix twind css settings --- tailwind.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tailwind.config.js b/tailwind.config.js index d854b46..409c3ef 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -17,6 +17,7 @@ module.exports = { gray: colors.gray, teal: colors.teal, blue: colors.blue, + transparent: colors.transparent, }, extend: {}, }, From e8ede48677f2b0c9d91e29faf67d21a1addc3c8e Mon Sep 17 00:00:00 2001 From: zukki30 Date: Thu, 26 May 2022 03:39:44 +0900 Subject: [PATCH 2/9] fix: Fix Router settins --- src/Router.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Router.tsx b/src/Router.tsx index 5cdb4c7..5373cf5 100644 --- a/src/Router.tsx +++ b/src/Router.tsx @@ -2,6 +2,7 @@ import { Route, ReactLocation } from "@tanstack/react-location"; import Home from "@/pages/Home"; import GraphDetail from "@/pages/GraphDetail"; +// const history = createHashHistory(); export const location = new ReactLocation(); export const routes: Route[] = [ @@ -10,7 +11,16 @@ export const routes: Route[] = [ element: , }, { - path: ":id", - element: , + path: "graph", + children: [ + { + path: "/", + element: , + }, + { + path: ":id", + element: , + }, + ], }, ]; From f7dbb2539938d1826f28257cfbf551b82fa246a5 Mon Sep 17 00:00:00 2001 From: zukki30 Date: Thu, 26 May 2022 03:40:13 +0900 Subject: [PATCH 3/9] feat: Add Loading components --- src/components/common/Loading.tsx | 35 ++++++++++++++++++++++++++ src/stories/common/Loading.stories.tsx | 13 ++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/components/common/Loading.tsx create mode 100644 src/stories/common/Loading.stories.tsx diff --git a/src/components/common/Loading.tsx b/src/components/common/Loading.tsx new file mode 100644 index 0000000..489bca3 --- /dev/null +++ b/src/components/common/Loading.tsx @@ -0,0 +1,35 @@ +import React from "react"; + +import styled from "styled-components"; +import tw from "twin.macro"; + +const LoadingContainer = styled.header` + ${tw` + w-full + h-screen + flex + justify-center + content-center + `} +`; + +const LoadingIcon = styled.div` + ${tw` + animate-spin + h-10 + w-10 + border-4 + border-sky-500 + rounded-full + border-t-transparent + `} +`; +const Loading = () => { + return ( + + + + ); +}; + +export default Loading; diff --git a/src/stories/common/Loading.stories.tsx b/src/stories/common/Loading.stories.tsx new file mode 100644 index 0000000..642155d --- /dev/null +++ b/src/stories/common/Loading.stories.tsx @@ -0,0 +1,13 @@ +import React from "react"; +import { ComponentStory, ComponentMeta } from "@storybook/react"; + +import Loading from "@/components/common/Loading"; + +export default { + title: "components/common/Loading", + component: Loading, +} as ComponentMeta; + +const Template: ComponentStory = () => ; + +export const Default = Template.bind({}); From 66429ecf002423a63df53bef8c9ab3eb69e49ee5 Mon Sep 17 00:00:00 2001 From: zukki30 Date: Thu, 26 May 2022 03:40:42 +0900 Subject: [PATCH 4/9] fix: Fix color-utils methos --- src/utils/color-utils.ts | 62 +++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/src/utils/color-utils.ts b/src/utils/color-utils.ts index 6728721..3e4d3f5 100644 --- a/src/utils/color-utils.ts +++ b/src/utils/color-utils.ts @@ -1,24 +1,66 @@ -import { ColorType } from "@/const/color"; +import { ColorType, graphBgColors, graphBorderColors } from "@/const/color"; /** - * index から ColorType を返す - * @param index: number + * graphBgColor から ColorType を返す + * @param graphBgColor: string * @returns */ -export const getColorType = (index: number): ColorType => { - if (index === 0 || index === 6) { +export const getColorType = (graphBgColor: string): ColorType => { + if (graphBgColor === graphBgColors[0] || graphBgColor === graphBgColors[6]) { return ColorType.RED; - } else if (index === 1 || index === 7) { + } else if (graphBgColor === graphBgColors[1] || graphBgColor === graphBgColors[7]) { return ColorType.ORANGE; - } else if (index === 2 || index === 8) { + } else if (graphBgColor === graphBgColors[2] || graphBgColor === graphBgColors[8]) { return ColorType.YELLOW; - } else if (index === 3 || index === 9) { + } else if (graphBgColor === graphBgColors[3] || graphBgColor === graphBgColors[9]) { return ColorType.GREEN; - } else if (index === 4 || index === 10) { + } else if (graphBgColor === graphBgColors[4] || graphBgColor === graphBgColors[10]) { return ColorType.BLUE; - } else if (index === 5 || index === 11) { + } else if (graphBgColor === graphBgColors[5] || graphBgColor === graphBgColors[11]) { return ColorType.PURPLE; } else { return ColorType.BLUE; } }; + +/** + * value の length から bg colors を取得する + * @param value Cost[] + * @returns + */ +export const getBgColoos = (value: Cost[]) => { + const result: string[] = []; + + if (value.length === 2) { + result.push(graphBgColors[0], graphBgColors[4]); + } else if (value.length === 3) { + result.push(graphBgColors[0], graphBgColors[3], graphBgColors[4]); + } else if (value.length === 4) { + result.push(graphBgColors[0], graphBgColors[2], graphBgColors[3], graphBgColors[4]); + } else { + result.push(...graphBgColors); + } + + return result; +}; + +/** + * value の length から border colors を取得する + * @param value Cost[] + * @returns + */ +export const getBorderColoos = (value: Cost[]) => { + const result: string[] = []; + + if (value.length === 2) { + result.push(graphBorderColors[0], graphBorderColors[4]); + } else if (value.length === 3) { + result.push(graphBorderColors[0], graphBorderColors[3], graphBorderColors[4]); + } else if (value.length === 4) { + result.push(graphBorderColors[0], graphBorderColors[2], graphBorderColors[3], graphBorderColors[4]); + } else { + result.push(...graphBorderColors); + } + + return result; +}; From 275304ba8972164a64bef29056a4212f89cab576 Mon Sep 17 00:00:00 2001 From: zukki30 Date: Thu, 26 May 2022 03:41:04 +0900 Subject: [PATCH 5/9] feat: Add buildTotalChart & buildTotalCharts methos --- src/utils/type-utils.ts | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/utils/type-utils.ts b/src/utils/type-utils.ts index 94df065..3ebd4d9 100644 --- a/src/utils/type-utils.ts +++ b/src/utils/type-utils.ts @@ -1,5 +1,5 @@ import { DocumentData } from "firebase/firestore"; -import { graphBgColors, graphBorderColors } from "@/const/color"; +import { getBorderColoos, getBgColoos } from "@/utils/color-utils"; /** * UserInfo type を作成する @@ -26,7 +26,7 @@ export const buildCosts = (doc: DocumentData) => { const data = doc.data(); return { - id: doc.id, + id: data.id, name: data.name, dates: data.dates, } as Cost; @@ -57,22 +57,8 @@ export const buildTotalChart = (value: Cost, backgroundColor: string, borderColo * @returns */ export const buildTotalCharts = (value: Cost[]) => { - const bgColors: string[] = []; - const borderColors: string[] = []; - - if (value.length === 2) { - bgColors.push(graphBgColors[0], graphBgColors[4]); - borderColors.push(graphBorderColors[0], graphBorderColors[4]); - } else if (value.length === 3) { - bgColors.push(graphBgColors[0], graphBgColors[3], graphBgColors[4]); - borderColors.push(graphBorderColors[0], graphBorderColors[3], graphBorderColors[4]); - } else if (value.length === 4) { - bgColors.push(graphBgColors[0], graphBgColors[2], graphBgColors[3], graphBgColors[4]); - borderColors.push(graphBorderColors[0], graphBorderColors[2], graphBorderColors[3], graphBorderColors[4]); - } else { - bgColors.push(...graphBgColors); - borderColors.push(...graphBorderColors); - } + const bgColors: string[] = getBgColoos(value); + const borderColors: string[] = getBorderColoos(value); return value.map((cost, index) => buildTotalChart(cost, bgColors[index], borderColors[index])); }; From 71cac4f81fd97924ed24dc4fe69a2cbe2b0e4547 Mon Sep 17 00:00:00 2001 From: zukki30 Date: Thu, 26 May 2022 03:41:37 +0900 Subject: [PATCH 6/9] feat: Add export to firestore --- src/providers/FirebaseProvider.tsx | 2 +- src/providers/UserProvider.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/providers/FirebaseProvider.tsx b/src/providers/FirebaseProvider.tsx index b1efbb4..9e08d13 100644 --- a/src/providers/FirebaseProvider.tsx +++ b/src/providers/FirebaseProvider.tsx @@ -46,7 +46,7 @@ const analytics = getAnalytics(app); const auth = getAuth(app); auth.setPersistence(browserLocalPersistence); -const firestore = getFirestore(app); +export const firestore = getFirestore(app); export const FirebaseProvider = ({ children }: { children: React.ReactNode }) => { const getQuerySnapshot = async (path: string, ...queryConstraints: QueryConstraint[]) => { diff --git a/src/providers/UserProvider.tsx b/src/providers/UserProvider.tsx index 18f67b0..afe1d70 100644 --- a/src/providers/UserProvider.tsx +++ b/src/providers/UserProvider.tsx @@ -34,7 +34,6 @@ export const UserProvider = ({ children }: { children: React.ReactNode }) => { setErrorMessage(""); await signInWithEmailAndPassword(auth, email, password) .then((userCredential) => { - console.log(userCredential.user.uid); setUid(userCredential.user.uid); }) .catch((error) => { From 6fd81a4ea8947f0337d177be7c07283dbcf4f1ad Mon Sep 17 00:00:00 2001 From: zukki30 Date: Thu, 26 May 2022 03:41:49 +0900 Subject: [PATCH 7/9] feat: Add swr-hooks --- src/hooks/swr-hooks.ts | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/hooks/swr-hooks.ts diff --git a/src/hooks/swr-hooks.ts b/src/hooks/swr-hooks.ts new file mode 100644 index 0000000..d2fc0f5 --- /dev/null +++ b/src/hooks/swr-hooks.ts @@ -0,0 +1,31 @@ +import useSWR from "swr"; +import { collection, getDocs, query } from "firebase/firestore"; +import { firestore } from "@/providers/FirebaseProvider"; +import { buildCosts } from "@/utils/type-utils"; + +const useFetcher = async (url: string) => { + const costsResult = await getDocs(query(collection(firestore, url))); + + return costsResult.docs.map(buildCosts); +}; + +/** + * useSWR を使用する + * @returns + */ +export const useFetchCostsWithSWR = (url: string) => { + const { + data, + error, + mutate: setCosts, + } = useSWR(url, useFetcher, { + revalidateIfStale: false, + revalidateOnFocus: false, + revalidateOnReconnect: false, + }); + const costs = data === undefined ? [] : data; + const isLoading = !error && !data; + const isError = error; + + return { costs, isLoading, isError, setCosts }; +}; From bfc1c6cc63b2946541eb1e0d9ba6c6237b453fa6 Mon Sep 17 00:00:00 2001 From: zukki30 Date: Thu, 26 May 2022 03:42:05 +0900 Subject: [PATCH 8/9] feat: Add swr-hooks to each pages --- src/pages/GraphDetail.tsx | 201 ++++++++++++-------------------------- src/pages/Home.tsx | 154 ++++------------------------- 2 files changed, 84 insertions(+), 271 deletions(-) diff --git a/src/pages/GraphDetail.tsx b/src/pages/GraphDetail.tsx index d2adb34..9f614e3 100644 --- a/src/pages/GraphDetail.tsx +++ b/src/pages/GraphDetail.tsx @@ -5,7 +5,12 @@ import { useNavigate, useLocation } from "@tanstack/react-location"; import styled from "styled-components"; import tw from "twin.macro"; -import { graphBgColors, graphBorderColors, ColorType } from "@/const/color"; +import { useUserContext } from "@/providers/UserProvider"; +import { useFetchCostsWithSWR } from "@/hooks/swr-hooks"; + +import { ColorType } from "@/const/color"; + +import Loading from "@/components/common/Loading"; import Button from "@/components/elements/Button"; import Title from "@/components/elements/Title"; @@ -14,7 +19,7 @@ import Table from "@/components/elements/Table"; import VerticalBarChart, { VerticalBarChartData } from "@/components/graph/VerticalBarChart"; -import { getColorType } from "@/utils/color-utils"; +import { getColorType, getBgColoos, getBorderColoos } from "@/utils/color-utils"; const DetailContainer = styled.div` ${tw` @@ -38,104 +43,15 @@ const DetailButton = styled(Button)` `} `; -const dummyCosts: Cost[] = [ - { - id: "credit-card-a", - name: "クレジットカードA", - dates: [ - { - label: "2020/08", - amount: 12300, - }, - { - label: "2020/09", - amount: 23300, - }, - { - label: "2020/10", - amount: 10000, - }, - { - label: "2020/11", - amount: 8300, - }, - { - label: "2020/12", - amount: 15700, - }, - { - label: "2021/01", - amount: 19000, - }, - ], - }, - { - id: "credit-card-b", - name: "クレジットカードB", - dates: [ - { - label: "2020/08", - amount: 10000, - }, - { - label: "2020/09", - amount: 13300, - }, - { - label: "2020/10", - amount: 4000, - }, - { - label: "2020/11", - amount: 6300, - }, - { - label: "2020/12", - amount: 4700, - }, - { - label: "2021/01", - amount: 9000, - }, - ], - }, - { - id: "credit-card-c", - name: "クレジットカードC", - dates: [ - { - label: "2020/08", - amount: 1500, - }, - { - label: "2020/09", - amount: 1300, - }, - { - label: "2020/10", - amount: 3000, - }, - { - label: "2020/11", - amount: 3300, - }, - { - label: "2020/12", - amount: 2700, - }, - { - label: "2021/01", - amount: 4500, - }, - ], - }, -]; - const GraphDetail = () => { + const { uid } = useUserContext(); + const costsUrl = `users/${uid}/costs`; + const { costs, isLoading } = useFetchCostsWithSWR(costsUrl); + const navigate = useNavigate(); const location = useLocation(); - const pageId = location.current.pathname.replace("/", ""); + const [cost, setCost] = useState(null); const [labels, setLabels] = useState([]); const [datasets, setDatasets] = useState([]); const data = { @@ -152,47 +68,58 @@ const GraphDetail = () => { }; useEffect(() => { - const result = dummyCosts; - const findResult = result.find((r) => r.id === pageId) as Cost; - const findIndex = result.findIndex((r) => r.id === pageId); - - setColorType(getColorType(findIndex)); - - const labels = findResult.dates.map((date) => date.label); - setLabels(labels); - setTableHeadData(["", ...labels]); - - const amounts = findResult.dates.map((date) => date.amount); - setDatasets([ - { - label: findResult.name, - data: amounts, - backgroundColor: graphBgColors[findIndex], - borderColor: graphBorderColors[findIndex], - borderWidth: 1, - }, - ]); - const tableBodyDataCells = [findResult.name, ...amounts.map((d) => d.toLocaleString())]; - setTableBodyData([tableBodyDataCells]); - }, [pageId]); - - return ( - - - - <DetailBody> - <Card> - <VerticalBarChart data={data} /> - </Card> - </DetailBody> - - <DetailBody> - <Table headColor={colorType} headData={tableHeadData} bodyData={tableBodyData} /> - </DetailBody> - - <DetailButton label="TOPに戻る" color="normal" onClick={handleClick} /> - </DetailContainer> - ); + if (costs.length > 0) { + const bgColors = getBgColoos(costs); + const borderColors = getBorderColoos(costs); + + const pageId = location.current.pathname.replace("/graph/", ""); + const findResult = costs.find((cost) => cost.id === pageId) as Cost; + setCost(findResult); + + const findIndex = costs.findIndex((cost) => cost.id === pageId); + + setColorType(getColorType(bgColors[findIndex])); + + const labels = findResult.dates.map((date) => date.label); + setLabels(labels); + setTableHeadData(["", ...labels]); + + const amounts = findResult.dates.map((date) => date.amount); + setDatasets([ + { + label: findResult.name, + data: amounts, + backgroundColor: bgColors[findIndex], + borderColor: borderColors[findIndex], + borderWidth: 1, + }, + ]); + const tableBodyDataCells = [findResult.name, ...amounts.map((d) => d.toLocaleString())]; + setTableBodyData([tableBodyDataCells]); + } + }, [costs, location]); + + if (isLoading && cost === null) { + return <Loading />; + } else { + return ( + <DetailContainer> + <Title text={`${cost?.name}の1年間のデータ`} level={1} color={colorType} /> + + <DetailBody> + <Card> + <VerticalBarChart data={data} /> + </Card> + </DetailBody> + + <DetailBody> + <Table headColor={colorType} headData={tableHeadData} bodyData={tableBodyData} /> + </DetailBody> + + <DetailButton label="TOPに戻る" color="normal" onClick={handleClick} /> + </DetailContainer> + ); + } }; export default GraphDetail; diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 138b456..1375c63 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -1,15 +1,16 @@ import { FC, useState, useEffect } from "react"; -// import { FC, useCallback, useEffect } from "react"; -// import { useFirebaseContext } from "@/providers/FirebaseProvider"; -// import { useUserContext } from "@/providers/UserProvider"; -// import { buildUserInfo, buildCosts } from "@/utils/type-utils"; -import { buildTotalCharts } from "@/utils/type-utils"; import { useNavigate } from "@tanstack/react-location"; +import { useUserContext } from "@/providers/UserProvider"; +import { buildTotalCharts } from "@/utils/type-utils"; +import { useFetchCostsWithSWR } from "@/hooks/swr-hooks"; + import styled from "styled-components"; import tw from "twin.macro"; +import Loading from "@/components/common/Loading"; + import Title from "@/components/elements/Title"; import Card from "@/components/elements/Card"; @@ -54,106 +55,10 @@ const CardGraph = styled.div` `}; `; -const dummyCosts: Cost[] = [ - { - id: "credit-card-a", - name: "クレジットカードA", - dates: [ - { - label: "2020/08", - amount: 12300, - }, - { - label: "2020/09", - amount: 23300, - }, - { - label: "2020/10", - amount: 10000, - }, - { - label: "2020/11", - amount: 8300, - }, - { - label: "2020/12", - amount: 15700, - }, - { - label: "2021/01", - amount: 19000, - }, - ], - }, - { - id: "credit-card-b", - name: "クレジットカードB", - dates: [ - { - label: "2020/08", - amount: 10000, - }, - { - label: "2020/09", - amount: 13300, - }, - { - label: "2020/10", - amount: 4000, - }, - { - label: "2020/11", - amount: 6300, - }, - { - label: "2020/12", - amount: 4700, - }, - { - label: "2021/01", - amount: 9000, - }, - ], - }, - { - id: "credit-card-c", - name: "クレジットカードC", - dates: [ - { - label: "2020/08", - amount: 1500, - }, - { - label: "2020/09", - amount: 1300, - }, - { - label: "2020/10", - amount: 3000, - }, - { - label: "2020/11", - amount: 3300, - }, - { - label: "2020/12", - amount: 2700, - }, - { - label: "2021/01", - amount: 4500, - }, - ], - }, -]; - const Home: FC = () => { - // const { getQuerySnapshot, getDocumentSnapshot } = useFirebaseContext(); - // const { uid } = useUserContext(); - // const usersCollectionName = "users"; - // const usersPath = `${usersCollectionName}/${uid}`; - // const costsCollectionName = "costs"; - // const costsPath = `${usersPath}/${costsCollectionName}`; + const { uid } = useUserContext(); + const costsUrl = `users/${uid}/costs`; + const { costs, isLoading } = useFetchCostsWithSWR(costsUrl); const navigate = useNavigate(); const [labels, setLabels] = useState<string[]>([]); @@ -167,42 +72,23 @@ const Home: FC = () => { labels, datasets: stackedBarDatasets, }; - const [costs, setCosts] = useState<Cost[]>([]); - // const [userInfos, setUserInfos] = useState<UserInfo[]>([]); const handleGraphClick = (data: ChartData) => { - navigate({ to: `${costs[data.datasetIndex].id}` }); + navigate({ to: `/graph/${costs[data.datasetIndex].id}` }); }; - // const fetch = useCallback(async () => { - // const userResult = getDocumentSnapshot(usersPath); - - // if ((await userResult).exists()) { - // const userInfo = buildUserInfo(userResult); - // console.log(userInfo); + useEffect(() => { + if (costs.length > 0) { + const labels = costs[0].dates.map((date) => date.label); + setLabels(labels); - // const costsResult = getQuerySnapshot(costsPath); - // const costs = await (await costsResult).docs.map(buildCosts); - // console.log(costs); - // } - // }, [getDocumentSnapshot, usersPath, getQuerySnapshot, costsPath]); + const totalCosts = buildTotalCharts(costs); + setLineDatasets(totalCosts); + setStackedBarDatasets(totalCosts); + } + }, [costs]); - useEffect(() => { - const result = dummyCosts; - setCosts(result); - - const labels = result[0].dates.map((date) => date.label); - setLabels(labels); - - const totalCosts = buildTotalCharts(result); - setLineDatasets(totalCosts); - setStackedBarDatasets(totalCosts); - // setUserInfos([ - // { - // id: - // } - // ]); - }, []); + if (isLoading) return <Loading />; return ( <> From 2f0a31286f84cc6430d2c947806defa76967c67a Mon Sep 17 00:00:00 2001 From: zukki30 <kw4869ify@gmail.com> Date: Thu, 26 May 2022 03:43:45 +0900 Subject: [PATCH 9/9] feat: Add meta robots to index.html --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index d327f91..9c5f4a7 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ <html lang="en"> <head> <meta charset="UTF-8" /> - <link rel="icon" type="image/svg+xml" href="/src/favicon.svg" /> + <meta name="robots" content="none" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>My cost check