diff --git a/.gitignore b/.gitignore
index 24cdedf..532eddc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,4 +20,6 @@
npm-debug.log*
yarn-debug.log*
-yarn-error.log*
\ No newline at end of file
+yarn-error.log*
+
+.env
\ No newline at end of file
diff --git a/src/components/Router.tsx b/src/components/Router.tsx
index 49eb1d5..9c54833 100644
--- a/src/components/Router.tsx
+++ b/src/components/Router.tsx
@@ -1,6 +1,7 @@
import { BrowserRouter, Route, Routes } from "react-router-dom";
import { Dashboard, Login, Main, User } from "pages";
+import UserDetail from "./user/UserDetail";
export default function Router() {
return (
@@ -9,7 +10,9 @@ export default function Router() {
} />
}>
} />
- } />
+ }>
+ } />
+
소중이들 미안! 404 에러야!} />
소중이들 미안! 404 에러야!} />
diff --git a/src/components/dashboard/Summary.tsx b/src/components/dashboard/Summary.tsx
index 6533da8..926d7af 100644
--- a/src/components/dashboard/Summary.tsx
+++ b/src/components/dashboard/Summary.tsx
@@ -1,12 +1,16 @@
import styled from "styled-components";
import { theme } from "styled-tools";
-export default function Summary({
- summaryIcon,
- summaryText,
- dataNumber,
- dataVariation,
-}) {
+interface SummaryProps {
+ summaryIcon: string;
+ summaryText: string;
+ dataNumber: string | number;
+ dataVariation: number;
+}
+
+export default function Summary(props: SummaryProps) {
+ const { summaryIcon, summaryText, dataNumber, dataVariation } = props;
+
return (
@@ -14,7 +18,13 @@ export default function Summary({
{summaryText}
{dataNumber}
- {dataVariation}
+ {dataVariation ? (
+
+ {dataVariation > 0
+ ? `( +${dataVariation} )`
+ : `( ${dataVariation} )`}
+
+ ) : null}
diff --git a/src/components/dashboard/SummaryWrapper.tsx b/src/components/dashboard/SummaryWrapper.tsx
index 9922429..53970fc 100644
--- a/src/components/dashboard/SummaryWrapper.tsx
+++ b/src/components/dashboard/SummaryWrapper.tsx
@@ -1,27 +1,71 @@
import Summary from "./Summary";
import styled from "styled-components";
import { joinUserIcon, totalUserIcon, totalPlantingIcon } from "../../assets";
+import { useSetRecoilState } from "recoil";
+import { userTotalNum } from "states";
+import { client } from "utils/api";
+import { useEffect, useState } from "react";
export default function SummaryWrapper() {
+ const [dashboardData, setDashboardData] = useState({
+ todayUserTotal: 0,
+ yesterdayUserTotal: 0,
+ todayContactTotal: 0,
+ });
+
+ const setUserTotalCount = useSetRecoilState(userTotalNum);
+
+ const convertDateToString = (date: Date) => {
+ return date.toISOString().split("T")[0];
+ };
+
+ const todayDate = convertDateToString(new Date());
+ const yesterdayDate = convertDateToString(
+ new Date(new Date().getTime() - 24 * 60 * 60 * 1000)
+ );
+
+ useEffect(() => {
+ (async function () {
+ const todayRes = await client(`/user/count?date=${todayDate}`);
+ const todayUserTotal = todayRes.data.data.totalCount;
+ setUserTotalCount(todayUserTotal);
+ const yesterdayRes = await client.get(
+ `/user/count?date=${yesterdayDate}`
+ );
+ const yesterdayUserTotal = yesterdayRes.data.data.totalCount;
+
+ const { data } = await client("/contact");
+
+ setDashboardData((current) => ({
+ ...current,
+ todayUserTotal,
+ yesterdayUserTotal,
+ todayContactTotal: data.count,
+ }));
+ })();
+ }, [todayDate, yesterdayDate, setUserTotalCount]);
+
return (
);
diff --git a/src/components/login/LoginForm.tsx b/src/components/login/LoginForm.tsx
index bfc1f67..a648dae 100644
--- a/src/components/login/LoginForm.tsx
+++ b/src/components/login/LoginForm.tsx
@@ -1,23 +1,51 @@
-import { Link } from "react-router-dom";
+import { useNavigate } from "react-router-dom";
import styled from "styled-components";
import { theme } from "styled-tools";
import { IdIcon, PwIcon } from "assets";
+import { useState } from "react";
export default function LoginWrapper() {
+ const [account, setAccount] = useState({ id: "", pwd: "" });
+ const navigate = useNavigate();
+
+ const checkIsAdmin = (e) => {
+ e.preventDefault();
+ console.log("account", account, process.env.REACT_APP_ADMIN_ID);
+ if (
+ account.id === `${process.env.REACT_APP_ADMIN_ID}` &&
+ account.pwd === `${process.env.REACT_APP_ADMIN_PWD}`
+ ) {
+ navigate("/main/dashboard");
+ }
+ };
+
return (
-
);
}
@@ -42,7 +70,7 @@ const StInput = styled.div`
}
`;
-const StLoginButton = styled.p`
+const StLoginButton = styled.button`
display: flex;
justify-content: center;
align-items: center;
diff --git a/src/components/user/PlantList.tsx b/src/components/user/PlantList.tsx
index d82f4b7..5f81305 100644
--- a/src/components/user/PlantList.tsx
+++ b/src/components/user/PlantList.tsx
@@ -1,19 +1,12 @@
-import { useEffect, useState } from "react";
import styled from "styled-components";
import { theme } from "styled-tools";
+import { Plant } from "./UserDetail";
-import { getPlantList } from "utils";
-import { Plant } from "utils/tempData";
-
-export default function PlantList() {
- const [plantList, setPlantList] = useState([]);
-
- useEffect(() => {
- (async function () {
- const plantData: Plant[] = await getPlantList();
- setPlantList(plantData);
- })();
- }, []);
+interface PlantListProps {
+ plantList: Plant[];
+}
+export default function PlantList(props: PlantListProps) {
+ const { plantList } = props;
return (
@@ -25,12 +18,12 @@ export default function PlantList() {
최근 물주기 날짜
누적 물주기
- {plantList.map((plant) => (
-
+ {plantList.map((plant, idx) => (
+
{plant.name}
- {plant.period}일
- {plant.recentDate}
- {plant.accumulated}회
+ {plant.waterInterval}일
+ {plant.lastWaterDate}
+ {plant.waterCount}회
))}
diff --git a/src/components/user/UserDetail.tsx b/src/components/user/UserDetail.tsx
index 4b458e6..259b543 100644
--- a/src/components/user/UserDetail.tsx
+++ b/src/components/user/UserDetail.tsx
@@ -1,36 +1,40 @@
import { useEffect, useState } from "react";
import styled from "styled-components";
-import { getUserInfo } from "utils";
-import { User } from "utils/tempData";
import { PlantList, UserInfo } from "..";
-import { plant1 } from "assets";
import { theme } from "styled-tools";
+import { useRecoilValue } from "recoil";
+import { userDatum, UserDatum } from "states";
+import { client } from "utils/api";
-const TEMP_USER_ID: number = 5;
-const INITIAL_PROPS: User = {
- id: 0,
- image: "",
- nickname: "temp",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
-};
+export interface Plant {
+ name: string;
+ waterInterval: number;
+ lastWaterDate: string;
+ waterCount: number;
+}
export default function UserDetail() {
- const [userInfo, setUserInfo] = useState(INITIAL_PROPS);
+ const [plantList, setPlantList] = useState([]);
+ const user: UserDatum = useRecoilValue(userDatum);
useEffect(() => {
(async function () {
- const userData: User = await getUserInfo(TEMP_USER_ID);
- setUserInfo({ ...userData, image: plant1 });
+ try {
+ const {
+ data: { plants },
+ } = await client.get(`/user/user/${user.id}`);
+ setPlantList(plants);
+ } catch (err) {
+ console.log("err", err);
+ }
})();
- }, []);
+ }, [user]);
return (
-
-
+
+
);
}
diff --git a/src/components/user/UserInfo.tsx b/src/components/user/UserInfo.tsx
index f734a49..94bb109 100644
--- a/src/components/user/UserInfo.tsx
+++ b/src/components/user/UserInfo.tsx
@@ -1,13 +1,25 @@
+import { useEffect } from "react";
import styled from "styled-components";
import { theme } from "styled-tools";
-import { User } from "utils/tempData";
+interface UserInfoProps {
+ id: number;
+ nickname: string;
+ email: string;
+ thumbNail?: string;
+}
-export default function UserInfo(props: { userInfo: User }) {
+export default function UserInfo(props: { userInfo: UserInfoProps }) {
const userInfo = props.userInfo;
+ useEffect(() => {
+ console.log(userInfo);
+ }, [userInfo]);
+
return (
-
+ {userInfo.thumbNail ? (
+
+ ) : null}
{userInfo.nickname}
{userInfo.email}
diff --git a/src/components/userList/UserList.tsx b/src/components/userList/UserList.tsx
index ab299e6..e4382d1 100644
--- a/src/components/userList/UserList.tsx
+++ b/src/components/userList/UserList.tsx
@@ -1,52 +1,61 @@
-import { useState, useEffect } from "react";
import styled from "styled-components";
import { theme } from "styled-tools";
-import { client } from "utils/api";
import { User } from "utils/tempData";
import { plant1, plant2, plant3, plant4, plant5 } from "assets";
-import { Link } from "react-router-dom";
+import { useNavigate } from "react-router-dom";
+import { useSetRecoilState } from "recoil";
+import { userDatum } from "states";
-interface Data {
- totalPages: number;
- totalUserCount: number;
- users: User[];
-}
-export default function UserList(props: { pageCnt: number }) {
- const [userList, setUserList] = useState([]);
+export default function UserList(props: { userList: User[] }) {
+ const { userList } = props;
const plantImages = [plant1, plant2, plant3, plant4, plant5];
+ const navigate = useNavigate();
+
+ const setUserDatum = useSetRecoilState(userDatum);
const getRandomNum = () => {
const randomNum = Math.floor(Math.random() * 4);
return randomNum;
};
- useEffect(() => {
- (async function () {
- const { data } = await client.get("/user", {
- params: {
- offset: props.pageCnt,
- count: 20,
- },
- });
- setUserList(data.users);
- })();
- }, [props.pageCnt]);
+ const navigateUserPage = (datum: User, image: string) => {
+ navigate(`/main/user`);
+ setUserDatum({
+ id: datum.id,
+ nickname: datum.nickname,
+ email: datum.email,
+ thumbNail: image,
+ });
+ };
return (
{userList &&
- userList.map((userInfo) => (
-
-
-
- {userInfo.nickname}
- {userInfo.email}
- {userInfo.phone}
- {userInfo.count}
+ userList.map((userInfo) => {
+ const userThumbNail = plantImages[getRandomNum()];
+ return (
+ navigateUserPage(userInfo, userThumbNail)}
+ >
+
+
+ {userInfo.nickname}
+
+
+ {userInfo.email}
+
+
+ {userInfo.phone}
+
+
+ {userInfo.count}
+
-
- ))}
+ );
+ })}
);
}
diff --git a/src/components/userList/UserListWrapper.tsx b/src/components/userList/UserListWrapper.tsx
index 634d76e..204362b 100644
--- a/src/components/userList/UserListWrapper.tsx
+++ b/src/components/userList/UserListWrapper.tsx
@@ -1,13 +1,30 @@
-import { useState } from "react";
+import { useEffect, useState } from "react";
import { theme } from "styled-tools";
-import styled from "styled-components";
+import styled, { css } from "styled-components";
import UserList from "./UserList";
import { ArrowLeft, ArrowRight } from "../../assets";
+import { User } from "utils/tempData";
+import { client } from "utils/api";
+import { useRecoilValue } from "recoil";
+import { userTotalNum } from "states";
+
+interface Data {
+ totalPages: number;
+ totalUserCount: number;
+ users: User[];
+}
+
+interface UserListWrapperProps {
+ shouldSetHeight: boolean;
+}
-export default function UserListWrapper() {
- const MAX_PAGE = 5;
+export default function UserListWrapper(props: UserListWrapperProps) {
+ const { shouldSetHeight } = props;
+ const [userList, setUserList] = useState([]);
+
+ const MAX_PAGE = useRecoilValue(userTotalNum) / 20;
const [pageCnt, setPageCnt] = useState(1);
const [isLeftActive, setIsLeftActive] = useState(true);
const [isRightActive, setIsRightActive] = useState(true);
@@ -30,8 +47,20 @@ export default function UserListWrapper() {
if (newCnt >= MAX_PAGE) setIsRightActive(false);
};
+ useEffect(() => {
+ (async function () {
+ const { data } = await client.get("/user", {
+ params: {
+ offset: pageCnt,
+ count: 20,
+ },
+ });
+ setUserList(data.users);
+ })();
+ }, [pageCnt]);
+
return (
-
+
사용자 목록
@@ -40,14 +69,18 @@ export default function UserListWrapper() {
-
+
);
}
-const StUserListWrapper = styled.article`
+const StUserListWrapper = styled.article<{ shouldset: boolean }>`
width: 100%;
- height: 100%;
+ ${({ shouldset }) =>
+ shouldset &&
+ css`
+ height: 100%;
+ `}
padding: 3.8rem;
background-color: ${theme("colors.bgWhite")};
diff --git a/src/pages/Dashboard.tsx b/src/pages/Dashboard.tsx
index f9bfe39..62ec621 100644
--- a/src/pages/Dashboard.tsx
+++ b/src/pages/Dashboard.tsx
@@ -14,7 +14,7 @@ export default function Dashboard() {
-
+
diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx
index 87774fc..4ecd00a 100644
--- a/src/pages/Login.tsx
+++ b/src/pages/Login.tsx
@@ -1,26 +1,9 @@
-import { useEffect, useState } from "react";
-
import styled from "styled-components";
import { theme } from "styled-tools";
-import { client } from "utils/api";
import { logo } from "assets";
import LoginWrapper from "components/login/LoginForm";
export default function Login() {
- const [temp, setTemp] = useState();
-
- const fetch = async () => {
- const data: any = client.get("/contact");
- setTemp(data);
- };
- useEffect(() => {
- fetch();
- }, []);
-
- useEffect(() => {
- console.log(temp);
- }, [temp]);
-
return (
diff --git a/src/pages/User.tsx b/src/pages/User.tsx
index 7fce20c..b531ba1 100644
--- a/src/pages/User.tsx
+++ b/src/pages/User.tsx
@@ -6,7 +6,7 @@ import { UserDetail } from "components";
export default function User() {
return (
-
+
);
diff --git a/src/states/index.ts b/src/states/index.ts
index 549e326..4151075 100644
--- a/src/states/index.ts
+++ b/src/states/index.ts
@@ -1,5 +1,22 @@
-import { atom } from "recoil";
-// import { selector } from "recoil";
+import { logo } from "assets";
+import { atom, RecoilState } from "recoil";
+
+export interface UserDatum {
+ id: number;
+ nickname: string;
+ email: string;
+ thumbNail: string;
+}
+
+export const userDatum: RecoilState = atom({
+ key: "userInfo",
+ default: {
+ id: -1,
+ nickname: "소중이",
+ email: "cherish@test.test",
+ thumbNail: logo,
+ },
+});
export type SelectedDate = { year: number; month: number };
@@ -16,10 +33,7 @@ export const waterSelectedDateAtom = atom({
default: defaultDate,
});
-// export const isLikeAtom = selector({
-// key: "isLikeClicked",
-// get: ({ get }) => {
-// const { isLike, likeNumber } = get(articleAtom);
-// return { status: isLike, number: likeNumber };
-// },
-// });
+export const userTotalNum: RecoilState = atom({
+ key: "userInfo",
+ default: 0,
+});
diff --git a/src/styles/global-style.ts b/src/styles/global-style.ts
index e3a8857..d1834a8 100644
--- a/src/styles/global-style.ts
+++ b/src/styles/global-style.ts
@@ -20,7 +20,7 @@ export const GlobalStyle = createGlobalStyle`
html {
color: ${theme("colors.textBlack")};
font-family: NotoSansKR;
- font-size: 10px;
+ font-size: 62.5%;
}
a {
diff --git a/src/utils/api.ts b/src/utils/api.ts
index bf74162..3013e17 100644
--- a/src/utils/api.ts
+++ b/src/utils/api.ts
@@ -1,7 +1,7 @@
import axios from "axios";
export const client = axios.create({
- baseURL: "http://localhost:5005",
+ baseURL: process.env.REACT_APP_BASE_URL,
headers: {
"Content-Type": "application/json",
},
diff --git a/src/utils/index.ts b/src/utils/index.ts
index e71f6b1..0194e18 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -1,17 +1,9 @@
-import { USER_LIST, DATE_JOIN_LIST, PLANT_LIST } from "./tempData";
-
-export const getUserList = async () => {
- return USER_LIST;
-};
+import { DATE_JOIN_LIST, PLANT_LIST } from "./tempData";
export const getDateJoinList = async () => {
return DATE_JOIN_LIST;
};
-export const getUserInfo = async (id: number) => {
- return USER_LIST.filter((user) => user.id === id)[0];
-};
-
export const getPlantList = async () => {
return PLANT_LIST;
};
diff --git a/src/utils/tempData.ts b/src/utils/tempData.ts
index ec9d74b..63f8159 100644
--- a/src/utils/tempData.ts
+++ b/src/utils/tempData.ts
@@ -1,6 +1,6 @@
export interface User {
id: number;
- image?: string;
+ image: string;
nickname: string;
email: string;
phone: string;
@@ -32,149 +32,6 @@ interface DateJoin {
count: number;
}
-export const USER_LIST: User[] = [
- {
- id: 1,
- nickname: "01짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 2,
- nickname: "02짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 3,
- nickname: "03짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 4,
- nickname: "04짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 5,
- nickname: "05짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 6,
- nickname: "06짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 7,
- nickname: "07짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 8,
- nickname: "08짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 9,
- nickname: "09짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 10,
- nickname: "10짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 11,
- nickname: "11짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 12,
- nickname: "12짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 13,
- nickname: "13짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 14,
- nickname: "14짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 15,
- nickname: "15짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 16,
- nickname: "16짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 17,
- nickname: "17짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 18,
- nickname: "18짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 19,
- nickname: "19짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
- {
- id: 20,
- nickname: "20짱구엄마",
- email: "temp@temp.com",
- phone: "0000",
- count: "00",
- },
-];
-
export const DATE_JOIN_LIST: DateJoin[] = [
{ date: "21-07-01", count: 1 },
{ date: "21-07-02", count: 1 },