Skip to content

Commit

Permalink
[ merge in dev ] 뱃지 api 연결
Browse files Browse the repository at this point in the history
[ feat ] 뱃지 api 연결
  • Loading branch information
NeatKYU authored Sep 4, 2023
2 parents 7b97607 + 89d2956 commit fce137b
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 68 deletions.
7 changes: 0 additions & 7 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,12 @@ import '@/styles/global.scss';
import { router } from '@/routes';
import { RouterProvider } from 'react-router-dom';
import { Toaster } from 'react-hot-toast';
import badgeIcon from '@/assets/img/badge_toast_example.png';
import { useEffect } from 'react';
import { BadgeToast } from './components/toast/BadgeToast';

declare global {
let Kakao: any;
}

function App() {
useEffect(() => {
BadgeToast({ badgeIcon, badgeName: '첫 번째 목표' });
}, []);

return (
<div className="select-none">
<RouterProvider router={router} />
Expand Down
18 changes: 18 additions & 0 deletions src/api/badge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { get } from './core';

export interface badgeDate {
regDtm: string;
}
export interface badge {
badgeId: string;
badgeName: string;
badgeCnt: number;
imageUrl: string;
explanation: string;
qualification: string;
gainDate: badgeDate[];
gainYn: 'Y' | 'N';
}
export const getBadges = async (): Promise<badge[]> => {
return await get('/badge/list');
};
35 changes: 15 additions & 20 deletions src/pages/badge/components/BadgeList.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,43 @@
import { ReactComponent as LockIcon } from '@/assets/img/icn_lock.svg';
import BadgeCount from './BadgeCount';

type Badge = {
imgSrc: string;
name: string;
key: number;
count: number;
locked: boolean;
};
import type { badge } from '@/api/badge';

type BadgeListProps = {
badgeList: Badge[];
clickHandler: (key: number) => void;
badgeList: badge[];
clickHandler: (id: string, badgeList: badge[]) => void;
};

const BadgeList = ({ badgeList, clickHandler }: BadgeListProps) => {
return (
<ul className="mt-5 mb-10 grid gap-x-3 gap-y-10 justify-center grid-cols-auto-fill">
{badgeList.map((badge) => (
<li className="flex-none" key={badge.key} onClick={() => clickHandler(badge.key)}>
<li className="flex-none" key={badge.badgeId} onClick={() => clickHandler(badge.badgeId, badgeList)}>
<BadgeItem badge={badge} />
</li>
))}
</ul>
);
};

type BadgeItemProps = {
badge: Badge;
};

const BadgeItem = ({ badge }: BadgeItemProps) => {
const BadgeItem = ({ badge }: { badge: badge }) => {
const isLock = badge.gainYn === 'N';
return (
<div className="flex flex-col justify-center items-center ">
<div className="relative">
<img className={`${badge.locked ? 'grayscale' : ''} object-none`} src={badge.imgSrc} />
{badge.locked && (
<div className="w-[100px] h-[100px]">
<img
className={`${isLock ? 'grayscale' : ''} object-contain w-full h-full`}
src={import.meta.env.VITE_STORAGE_URL + badge.badgeId + '.png'}
/>
</div>
{isLock && (
<div className="w-full h-full absolute bg-white/90 top-0 flex justify-center items-center">
<LockIcon />
</div>
)}
{badge.count > 1 && <BadgeCount count={badge.count} />}
{badge.badgeCnt > 1 && <BadgeCount count={badge.badgeCnt} />}
</div>
<span className={`${badge.locked ? 'text-gray-300' : 'text-gray-900'} mt-[11px]`}>{badge.name}</span>
<span className={`${isLock ? 'text-gray-300' : 'text-gray-900'} mt-[11px]`}>{badge.badgeName}</span>
</div>
);
};
Expand Down
35 changes: 16 additions & 19 deletions src/pages/badge/detail.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,26 @@
import { useLoaderData } from 'react-router-dom';
import exampleImg from '@/assets/img/badge_example_big.png';
import BadgeCount from './components/BadgeCount';

type BadgeInfo = {
count: number;
description: string;
acquiredAt: string[];
};
import { useLocation } from 'react-router-dom';
import { badgeDate } from '@/api/badge';
import { parsingDotDate } from '@/utils/date';

export default function BadgeDetail() {
const badgeInfo = useLoaderData() as BadgeInfo;

const props = useLocation().state;
return (
<div className="flex flex-col justify-center items-center">
<div className="flex flex-col justify-center items-center gap-9">
<div className="relative">
<img src={exampleImg} />
<BadgeCount count={badgeInfo.count} />
<div className="w-[200px] h-[200px]">
<img src={props.imgUrl} className="w-full h-full object-contain" />
</div>
<BadgeCount count={props.count ?? 0} />
</div>
<div className="flex flex-col items-center">
<span className="text-gray-900 font-bold text-base mb-2">{badgeInfo.description}</span>
{badgeInfo.acquiredAt.map((acquired, idx) => (
<span key={idx} className="text-base text-gray-600">
획득일: {acquired}
</span>
))}
<span className="text-gray-900 font-bold text-base mb-2">{props.name}</span>
{props &&
props.dates.map((date: badgeDate, idx: number) => (
<div key={idx} className="text-base text-gray-600">
획득일: {parsingDotDate(date.regDtm)}
</div>
))}
</div>
</div>
);
Expand Down
37 changes: 24 additions & 13 deletions src/pages/badge/index.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,40 @@
import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import BadgeList from './components/BadgeList';
import exampleImg from '@/assets/img/badge_example.png';
import { getBadges, badge } from '@/api/badge';

export default function BadgePage() {
const navigate = useNavigate();
const [badges, setBadges] = useState<badge[]>([]);

const fakeBadgeList = Array.from({ length: 20 }).map((_, idx) => ({
name: '완벽한 출발',
imgSrc: exampleImg,
key: idx,
locked: idx % 2 ? true : false,
count: 3,
}));
useEffect(() => {
getBadgeList();
}, []);

const routeToBadgeDetail = (key: number) => {
const badge = fakeBadgeList.find((badge) => badge.key === key);
const getBadgeList = async () => {
const result = await getBadges();
setBadges(result);
};

const routeToBadgeDetail = (id: string, badgeList: badge[]) => {
const badge = badgeList.find((badge) => badge.badgeId === id);

if (!badge?.locked) {
navigate(`/badge/${key}`);
if (badge && badge.badgeCnt > 0) {
navigate(`/badge/${badge.badgeId}`, {
state: {
name: badge.badgeName,
count: badge.badgeCnt,
dates: badge.gainDate,
explanation: badge.explanation,
imgUrl: import.meta.env.VITE_STORAGE_URL + badge.badgeId + '.png',
},
});
}
};

return (
<div>
<BadgeList badgeList={fakeBadgeList} clickHandler={routeToBadgeDetail} />
<BadgeList badgeList={badges} clickHandler={routeToBadgeDetail} />
</div>
);
}
9 changes: 0 additions & 9 deletions src/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,6 @@ export const router = createBrowserRouter([
{
path: ':badgeId',
element: <BadgeDetail />,
loader: ({ params }) => {
return {
key: params.badgeId,
name: '뱃지명',
description: '뱃지 설명',
count: 3,
acquiredAt: ['2023.07.14', '2023.07.15'],
};
},
},
],
},
Expand Down
9 changes: 9 additions & 0 deletions src/utils/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,12 @@ export const isSameDate = (date1: Date, date2: Date) => {
date1.getDate() === date2.getDate()
);
};

export const parsingDotDate = (date: Date | string) => {
const newDate = new Date(date);
const year = newDate.getFullYear();
const month = String(newDate.getMonth() + 1).padStart(2, '0');
const day = String(newDate.getDate()).padStart(2, '0');

return `${year}.${month}.${day}`;
};

0 comments on commit fce137b

Please sign in to comment.