Skip to content

Commit

Permalink
build: 프로젝트 초기 세팅
Browse files Browse the repository at this point in the history
- 품절 토글 버튼 스타일
- UserType 명시
- 식단 Suspense 추가
  • Loading branch information
junghaesung79 committed Jun 14, 2024
1 parent a642eed commit 749b0a4
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 68 deletions.
2 changes: 1 addition & 1 deletion src/api/dinings/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { accessClient } from 'api';
import { Dinings, DiningsParams } from 'models/dinings';

export const getDining = async (date: DiningsParams) => {
export const getDinings = async (date: DiningsParams) => {
const { data } = await accessClient.get<DiningsParams>(`/dinings?date=${date}`);
return Dinings.parse(data);
};
36 changes: 18 additions & 18 deletions src/models/auth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
import { z } from 'zod';

export const UserType = z.union([
z.literal('COOP'),
z.null(),
]);

export type UserType = z.infer<typeof UserType>;

export const CoopMeResponse = z.object({
email: z.string(),
gender: z.number().nullable(),
name: z.string(),
phone_number: z.string(),
user_type: UserType,
});

export type CoopMeResponse = z.infer<typeof CoopMeResponse>;

export const LoginParams = z.object({
email: z.string(),
password: z.string(),
Expand All @@ -14,7 +31,7 @@ export interface LoginForm extends LoginParams {
export const LoginResponse = z.object({
token: z.string(),
refresh_token: z.string(),
user_type: z.string(), // 삭제 가능성 있음
user_type: UserType, // 삭제 가능성 있음
});

export type LoginResponse = z.infer<typeof LoginResponse>;
Expand All @@ -31,20 +48,3 @@ export const RefreshResponse = z.object({
});

export type RefreshResponse = z.infer<typeof RefreshResponse>;

export const UserType = z.union([
z.literal('COOP'),
z.null(),
]);

export type UserType = z.infer<typeof UserType>;

export const CoopMeResponse = z.object({
email: z.string(),
gender: z.number().nullable(),
name: z.string(),
phone_number: z.string(),
user_type: UserType,
});

export type CoopMeResponse = z.infer<typeof CoopMeResponse>;
2 changes: 2 additions & 0 deletions src/models/dinings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,5 @@ export const Dining = z.object({
export type Dining = z.infer<typeof Dining>;

export const Dinings = z.array(Dining);

export type Dinings = z.infer<typeof Dinings>;
35 changes: 19 additions & 16 deletions src/pages/Coop/components/MenuCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
/* eslint-disable no-nested-ternary */
import { useEffect, useRef, useState } from 'react';
import {
Suspense, useEffect, useRef, useState,
} from 'react';

import { getCoopUrl } from 'api/uploadFile';
import Photo from 'assets/svg/coop/photo.svg?react';
import SoldOut from 'assets/svg/coop/sold-out.svg?react';
import { DiningPlace, Dining, DiningType } from 'models/dinings';
import {
DiningPlace, Dining, DiningType,
} from 'models/dinings';
import SoldOutModal from 'pages/Coop/components/SoldOutModal';
import SoldOutToggle from 'pages/Coop/components/SoldOutToggleButton';
import SoldOutToggleButton from 'pages/Coop/components/SoldOutToggleButton';
import { getOpenMenuType, OperatingStatus, OPEN } from 'pages/Coop/hook/useGetCurrentMenuType';
import { useUploadDiningImage, useSoldOut } from 'query/coop';
import { useGetDining as useGetDinings } from 'query/dinings';
import { useGetDinings } from 'query/dinings';

import axios from 'axios';

Expand All @@ -32,7 +36,7 @@ export default function MenuCard({ selectedMenuType, selectedDate }: Props) {
const [isSoldOutModalOpen, setIsSoldOutModalOpen] = useState(false);
const [selectedMenu, setSelectedMenu] = useState<Dining | null>(null);
const formattedDate = selectedDate.replace('-', '').replace('-', '').substring(2);
const { data } = useGetDinings(formattedDate);
const { data: dinings } = useGetDinings(formattedDate);
const [openMenu, setOpenMenu] = useState<OperatingStatus>(
getOpenMenuType(selectedMenuType, formattedDate),
);
Expand Down Expand Up @@ -77,7 +81,7 @@ export default function MenuCard({ selectedMenuType, selectedDate }: Props) {
fileInputRefs.current[menuId]?.click();
};

const filteredData = data.filter((menu: Dining) => ['A코너', 'B코너', 'C코너'].includes(menu.place));
const filteredData: Dining[] = dinings.filter((menu) => ['A코너', 'B코너', 'C코너'].includes(menu.place));

const getDiningDataForCorner = (
place: DiningPlace,
Expand Down Expand Up @@ -105,7 +109,7 @@ export default function MenuCard({ selectedMenuType, selectedDate }: Props) {
}, [selectedMenuType, formattedDate]);

return (
<>
<Suspense fallback={<div />}>
<div className={styles.container}>
{(['A코너', 'B코너', 'C코너'] as const).map((place) => {
const menu = getDiningDataForCorner(place, filteredData);
Expand All @@ -116,9 +120,7 @@ export default function MenuCard({ selectedMenuType, selectedDate }: Props) {
<div className={styles['card__common-wrapper']}>
<span className={styles.card__title}>{place}</span>
<div className={styles.card__kcal}>
{menu.kcal}
{' '}
kcal
{`${menu.kcal}kcal`}
</div>
<div className={styles.card__changed}>변경됨</div>
</div>
Expand All @@ -127,17 +129,18 @@ export default function MenuCard({ selectedMenuType, selectedDate }: Props) {
<div className={styles['card__common-wrapper']}>
<span className={styles.card__title}>{place}</span>
<div className={styles.card__kcal}>
{menu.kcal}
{' '}
kcal
{`${menu.kcal}kcal`}
</div>
</div>
)
)}
<div className={styles['card__common-wrapper']}>
{menu && <span className={styles.card__soldout}>품절</span>}
{menu && <span className={styles['card__sold-out']}>품절</span>}
{menu && (
<SoldOutToggle onClick={() => handleToggleSoldOutModal(menu)} menu={menu} />
<SoldOutToggleButton
menu={menu}
onClick={() => handleToggleSoldOutModal(menu)}
/>
)}
</div>
</div>
Expand Down Expand Up @@ -320,6 +323,6 @@ export default function MenuCard({ selectedMenuType, selectedDate }: Props) {
</div>
)}
</SoldOutModal>
</>
</Suspense>
);
}
2 changes: 2 additions & 0 deletions src/pages/Coop/components/MenuType/MenuType.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
flex-grow: 1;
height: 35px;
color: #8e8e8e;
background-color: #fff;
display: flex;
align-items: center;
justify-content: center;
Expand All @@ -27,6 +28,7 @@
flex-grow: 1;
height: 35px;
color: #175c8e;
background-color: #fff;
display: flex;
align-items: center;
justify-content: center;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
.toggle-button {
.container {
position: relative;
width: 46px;
height: 23px;
cursor: pointer;
-webkit-tap-highlight-color: rgb(0 0 0 / 0%);
-webkit-tap-highlight-color: transparent;
height: 22px;
border-radius: 11px;
background-color: #e1e1e1;

&--sold-out {
background-color: #175c8e;
}
}

.circle {
position: absolute;
top: 3px;
left: 3px;
width: 16px;
height: 16px;
border-radius: 8px;
background-color: #8e8e8e;
transition: all 0.3s;

&--sold-out {
transform: translateX(24px);
background-color: #fff;
}
}
38 changes: 20 additions & 18 deletions src/pages/Coop/components/SoldOutToggleButton/index.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import { Dining } from 'models/dinings';
import useToggleStore from 'store/useToggleStore';
import useSoldOutToggleStore from 'store/useSoldOutToggleStore';

Check warning on line 2 in src/pages/Coop/components/SoldOutToggleButton/index.tsx

View workflow job for this annotation

GitHub Actions / ESLint

'useSoldOutToggleStore' is defined but never used

Check warning on line 2 in src/pages/Coop/components/SoldOutToggleButton/index.tsx

View workflow job for this annotation

GitHub Actions / ESLint

'useSoldOutToggleStore' is defined but never used
import cn from 'utils/className';

import styles from './SoldOutToggleButton.module.scss';

interface Props {
onClick: () => void;
menu: Dining;
onClick: () => void;
}

function SoldOutToggleButton({ onClick, menu }: Props) {
const { toggleSoldOut } = useToggleStore();
const handleToggle = () => {
onClick();
toggleSoldOut(menu.id);
};

function SoldOutToggleButton({ menu, onClick }: Props) {
return (
<div>
<button
type="button"
className={styles['toggle-button']}
onClick={handleToggle}
>
버튼
</button>
</div>
<button
type="button"
aria-label="품절 버튼"
className={cn({
[styles.container]: true,
[styles['container--sold-out']]: !!menu.soldout_at,
})}
onClick={onClick}
>
<span
className={cn({
[styles.circle]: true,
[styles['circle--sold-out']]: !!menu.soldout_at,
})}
/>
</button>
);
}

Expand Down
15 changes: 7 additions & 8 deletions src/query/dinings.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { getDining } from 'api/dinings';
import { getDinings } from 'api/dinings';
import { Dinings } from 'models/dinings';

import { useSuspenseQuery } from '@tanstack/react-query';

export const useGetDining = (date: string) => {
const { data } = useSuspenseQuery(
{
queryKey: [date],
queryFn: () => getDining(date),
},
);
export const useGetDinings = (date: string) => {
const { data } = useSuspenseQuery<Dinings>({
queryKey: [date],
queryFn: () => getDinings(date),
});
return { data };
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ interface ToggleState {
toggleSoldOut: (menuId: number) => void;
}

const useToggleStore = create<ToggleState>((set) => ({
const useSoldOutToggleStore = create<ToggleState>((set) => ({
isSoldOut: {},
setInitialSoldOutState: (menuId: number, soldOut: string | null) => set((state) => ({
isSoldOut: {
Expand All @@ -27,4 +27,4 @@ const useToggleStore = create<ToggleState>((set) => ({
}),
}));

export default useToggleStore;
export default useSoldOutToggleStore;

0 comments on commit 749b0a4

Please sign in to comment.