Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement several major in ResultCategoryCard/#87 #89

Merged
merged 9 commits into from
May 2, 2024
18 changes: 15 additions & 3 deletions app/(sub-page)/result/page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import ResultCategoryCard from '@/app/ui/result/result-category-card';
import ResultCategoryDetail from '@/app/ui/result/result-category-detail/result-category-detail';
import ResultCategoryCard from '@/app/ui/result/result-category-card/result-category-card';
import UserInfoCard from '@/app/ui/user/user-info-card/user-info-card';
import ContentContainer from '@/app/ui/view/atom/content-container';
import { cn } from '@/app/utils/shadcn/utils';
import { RESULT_CATEGORY } from '@/app/utils/key/result-category.key';
import ResultCategoryDetail from '@/app/ui/result/result-category-detail/result-category-detail';

interface ResultPageProp {
searchParams: { category: string };
}

function ResultPage({ searchParams }: ResultPageProp) {
const { category } = searchParams;
const DUMMY_DATA = {
category: 'COMMON_CULTURE' as keyof typeof RESULT_CATEGORY,
totalCredit: 70,
takenCredit: 68,
completed: false,
};

return (
<div className="flex justify-center items-end">
Expand All @@ -23,7 +30,12 @@ function ResultPage({ searchParams }: ResultPageProp) {
)}
>
{Array.from({ length: 8 }).map((_, index) => (
<ResultCategoryCard key={index} />
<ResultCategoryCard
key={index}
category={RESULT_CATEGORY[DUMMY_DATA.category]}
totalCredit={DUMMY_DATA.totalCredit}
takenCredit={DUMMY_DATA.takenCredit}
/>
))}
</div>
{category && <ResultCategoryDetail category={category} />}
Expand Down
50 changes: 0 additions & 50 deletions app/ui/result/result-category-card.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { Meta, StoryObj } from '@storybook/react';
import ResultCategoryCard from './result-category-card';
import { RESULT_CATEGORY } from '@/app/utils/key/result-category.key';

const meta = {
title: 'ui/result/category-card',
component: ResultCategoryCard,
decorators: [(Story) => <Story />],
} as Meta<typeof ResultCategoryCard>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
category: RESULT_CATEGORY.COMMON_CULTURE,
totalCredit: 40,
takenCredit: 30,
completed: false,
},
};

export const CompletedSubMajor: Story = {
args: {
category: RESULT_CATEGORY.SUB_MAJOR,
totalCredit: 40,
takenCredit: 40,
completed: true,
},
};

export const UncompletedDualMajor = {
args: {
category: RESULT_CATEGORY.DUAL_BASIC_ACADEMICAL_CULTURE,
totalCredit: 70,
takenCredit: 40,
completed: false,
},
};
80 changes: 80 additions & 0 deletions app/ui/result/result-category-card/result-category-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
'use client';
import { cn } from '@/app/utils/shadcn/utils';

import Book from '@/public/assets/book.svg';
import Image from 'next/image';
import useDialog from '@/app/hooks/useDialog';
import * as React from 'react';
import { RESULT_CATEGORY, RESULT_CATEGORY_KO, ResultCategoryKey } from '@/app/utils/key/result-category.key';
import { DIALOG_KEY } from '@/app/utils/key/dialog-key.util';
import PieChart from '../../view/molecule/pie-chart/pie-chart';
import Button from '../../view/atom/button/button';
import { useRouter } from 'next/navigation';

interface ResultCategoryCardProps {
category: ResultCategoryKey;
totalCredit: number;
takenCredit: number;
completed?: boolean;
}

const filterSeveralMajor = (category: ResultCategoryKey) => {
const { DUAL_MANDATORY_MAJOR, DUAL_ELECTIVE_MAJOR, DUAL_BASIC_ACADEMICAL_CULTURE, SUB_MAJOR } = RESULT_CATEGORY;

switch (category) {
case DUAL_MANDATORY_MAJOR:
case DUAL_ELECTIVE_MAJOR:
case DUAL_BASIC_ACADEMICAL_CULTURE:
return <Button label="๋ณต์ˆ˜์ „๊ณต" variant="outlined" size="xs" role="none presentation" />;
case SUB_MAJOR:
return <Button label="๋ถ€์ „๊ณต" variant="outlined" size="xs" role="none presentation" />;
default:
return <></>;
}
};

function ResultCategoryCard({ category, totalCredit, takenCredit }: ResultCategoryCardProps) {
const { toggle } = useDialog(DIALOG_KEY.RESULT_CATEGORY);
const { replace } = useRouter();

const percentage = Number(((takenCredit / totalCredit) * 100).toFixed(0));

function handleClickButton() {
toggle();
replace('/result?category=COMMON_CULTURE');
}
return (
<div
className={cn('flex flex-col gap-6 zIndex-1 rounded-xl shadow-lg bg-white p-[0.4rem]', 'md:w-80 md:p-[1.8rem]')}
>
<div className="flex justify-between items-center">
<div className={cn('flex gap-4 font-bold text-sm', 'md:text-xl')}>
<Image src={Book} width={24} height={24} alt="category-img" />
<h3>{RESULT_CATEGORY_KO[category]}</h3>
</div>
{filterSeveralMajor(category)}
</div>
<div className="m-auto">
<PieChart percentage={percentage} />
</div>
<div className={cn('flex text-xs font-medium justify-between items-end', 'md:gap-4 md:text-base md:px-2')}>
<div>
<div className={cn('flex', 'md:gap-2')}>
<span>๊ธฐ์ค€ํ•™์ </span>
<span className="font-bold">{totalCredit}</span>
</div>
<div className={cn('flex', 'md:gap-2')}>
<span>์ด์ˆ˜ํ•™์ </span>
<span className={cn('font-bold', percentage === 100 ? 'text-point-blue' : 'text-etc-red')}>
{takenCredit}
</span>
</div>
</div>

<Button size="sm" label="๊ณผ๋ชฉ ํ™•์ธ" onClick={handleClickButton} />
</div>
</div>
);
}

export default ResultCategoryCard;
12 changes: 10 additions & 2 deletions app/ui/view/atom/button/button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const meta = {
docs: {
description: {
component: `
- variant๊ฐ’์œผ๋กœ "primary" | "secondary" | "text" | "delete" ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.\n
- variant๊ฐ’์œผ๋กœ "primary" | "secondary" | "list" | "outlined" ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.\n
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • 'list'๋ผ๋Š” ๋„ค์ด๋ฐ์„ ์‚ฌ์šฉํ•œ ์ด์œ ๊ฐ€ ์žˆ์„๊นŒ์š”?

Copy link
Member Author

@yougyung yougyung Apr 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ํ•ด๋‹น ๋„ค์ด๋ฐ์€ ๊ธฐ์กด์— ์กด์žฌํ•˜๋˜ variant๋กœ ์ƒˆ๋กญ๊ฒŒ ์ถ”๊ฐ€ ๋œ ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค
outlined๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉฐ ํ•จ๊ป˜ ์—…๋ฐ์ดํŠธ๋งŒ ์ง„ํ–‰ํ–ˆ์–ด์š” !

- size๊ฐ’์œผ๋กœ "lg" | "md" | "sm" | "xs" | "default" ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.\n
- label ๊ฐ’์œผ๋กœ button ํƒœ๊ทธ์— ์กด์žฌํ•˜๋Š” text๋ฅผ ์˜๋ฏธํ•˜๊ณ  ํ•„์ˆ˜์ ์œผ๋กœ ํ• ๋‹นํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค
`,
Expand All @@ -24,7 +24,7 @@ const meta = {
type: { summary: 'ButtonVariant' },
defaultValue: { summary: 'primary' },
},
options: ['primary', 'secondary', 'text', 'delete'],
options: ['primary', 'secondary', 'text', 'list', 'outlined'],
control: {
type: 'radio',
},
Expand Down Expand Up @@ -69,6 +69,14 @@ export const SecondaryButton: Story = {
},
};

export const OutlinedButton: Story = {
args: {
size: 'sm',
variant: 'outlined',
label: '์ฃผ์ „๊ณต',
},
};

export const ListActionButton: Story = {
args: {
size: 'default',
Expand Down
3 changes: 2 additions & 1 deletion app/ui/view/atom/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'default';

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
label: string;
variant?: 'primary' | 'secondary' | 'text' | 'list';
variant?: 'primary' | 'secondary' | 'text' | 'list' | 'outlined';
size?: ButtonSize;
loading?: boolean;
disabled?: boolean;
Expand All @@ -17,6 +17,7 @@ export const ButtonVariants = cva(`flex justify-center items-center`, {
variants: {
variant: {
primary: 'bg-primary rounded-[100px] text-white border-0 hover:bg-primary-hover',
outlined: 'rounded-[100px] text-primary border-solid border-[1px] border-primary',
secondary: 'bg-white rounded-[100px] border-solid border-[1px] border-gray-6 hover:bg-white-hover',
text: 'font-medium text-slate-400 text-sm hover:text-slate-600',
list: 'py-1 px-3 bg-blue-500 rounded-[7px] text-white leading-5 font-medium text-base hover:bg-blue-500',
Expand Down
12 changes: 11 additions & 1 deletion app/ui/view/molecule/pie-chart/pie-chart.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
position: absolute;
border-radius: 50%;
inset: 0;
background:
radial-gradient(farthest-side, #ff6d6d 98%, #0000) top/1.1rem 1.5rem no-repeat,
conic-gradient(#ff6d6d calc(var(--percentage) * 1%), #0000 0);
}

.piechart.complete::before {
background:
radial-gradient(farthest-side, #7590ff 98%, #0000) top/1.1rem 1.5rem no-repeat,
conic-gradient(#7590ff calc(var(--percentage) * 1%), #0000 0);
Expand All @@ -28,6 +34,10 @@
border-radius: 46%;
inset: calc(50% - 0.74rem);
position: absolute;
background: #7590ff;
background: #ff6d6d;
transform: rotate(calc(var(--percentage) * 3.6deg)) translateY(calc(50% - 9rem / 2));
}

.piechart.complete::after {
background: #7590ff;
}
13 changes: 11 additions & 2 deletions app/ui/view/molecule/pie-chart/pie-chart.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import '@/app/ui/view/molecule/pie-chart/pie-chart.css';
import { cn } from '@/app/utils/shadcn/utils';

export interface PieChartProp {
percentage: number;
Expand All @@ -9,10 +10,18 @@ function PieChart({ percentage }: PieChartProp) {

return (
<div
className={`piechart relative aspect-square rounded-full bg-light-blue-1 w-[9rem] h-[9rem]`}
className={cn(
'piechart relative aspect-square rounded-full w-[9rem] h-[9rem]',
percentage === 100 ? 'bg-light-blue-1 complete' : 'bg-etc-pink',
)}
style={{ '--percentage': percentage }}
>
<div className="absolute rounded-full bg-white text-light-blue-6 font-bold text-xl w-[6rem] h-[6rem] top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 flex justify-center items-center">
<div
className={cn(
'absolute rounded-full bg-white font-bold text-xl w-[6rem] h-[6rem] top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 flex justify-center items-center',
percentage === 100 ? 'text-light-blue-6' : 'text-etc-red',
)}
>
{filterdPercentage}%
</div>
</div>
Expand Down
31 changes: 31 additions & 0 deletions app/utils/key/result-category.key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export const RESULT_CATEGORY = {
COMMON_CULTURE: 'COMMON_CULTURE',
CORE_CULTURE: 'CORE_CULTURE',
PRIMARY_MANDATORY_MAJOR: 'PRIMARY_MANDATORY_MAJOR',
PRIMARY_ELECTIVE_MAJOR: 'PRIMARY_ELECTIVE_MAJOR',
DUAL_MANDATORY_MAJOR: 'DUAL_MANDATORY_MAJOR',
DUAL_ELECTIVE_MAJOR: 'DUAL_ELECTIVE_MAJOR',
SUB_MAJOR: 'SUB_MAJOR',
PRIMARY_BASIC_ACADEMICAL_CULTURE: 'PRIMARY_BASIC_ACADEMICAL_CULTURE',
DUAL_BASIC_ACADEMICAL_CULTURE: 'DUAL_BASIC_ACADEMICAL_CULTURE',
NORMAL_CULTURE: 'NORMAL_CULTURE',
FREE_ELECTIVE: 'FREE_ELECTIVE',
CHAPEL: 'CHAPEL',
} as const;
Comment on lines +1 to +14
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๋‹จ์–ด ๋œป์„ ์•Œ์•„๋„ ๋ฐ”๋กœ ์™€๋‹ฟ์ง€ ์•Š์€ ๊ฒƒ๋“ค์ด ์ข€ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์•„์š” ์˜ˆ๋ฅผ ๋“ค์–ด basic academical culture,,,
์ฃผ์„์œผ๋กœ ์˜๋ฏธ๋ฅผ ์จ์ฃผ๋ฉด ๋” ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”!

Copy link
Member Author

@yougyung yougyung Apr 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ํ•˜์œ„์— RESULT_CATEGORY_KO๋ฅผ ํ†ตํ•ด ๋งค์นญ๋˜๋Š” ํ•œ๊ธ€์˜๋ฏธ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
DUAL์€ ๋ณต์ˆ˜์ „๊ณต์„ ์˜๋ฏธํ•˜๊ณ  SUB์€ ๋ถ€์ „๊ณต์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.


export const RESULT_CATEGORY_KO = {
COMMON_CULTURE: '์ผ๋ฐ˜๊ต์–‘',
CORE_CULTURE: 'ํ•ต์‹ฌ๊ต์–‘',
PRIMARY_MANDATORY_MAJOR: '์ „๊ณตํ•„์ˆ˜',
PRIMARY_ELECTIVE_MAJOR: '์ „๊ณต์„ ํƒ',
DUAL_MANDATORY_MAJOR: '์ „๊ณตํ•„์ˆ˜',
DUAL_ELECTIVE_MAJOR: '์ „๊ณต์„ ํƒ',
SUB_MAJOR: '์ „๊ณต์„ ํƒ',
PRIMARY_BASIC_ACADEMICAL_CULTURE: 'ํ•™๋ฌธ๊ธฐ์ดˆ๊ต์–‘',
DUAL_BASIC_ACADEMICAL_CULTURE: 'ํ•™๋ฌธ๊ธฐ์ดˆ๊ต์–‘',
NORMAL_CULTURE: '์ผ๋ฐ˜๊ต์–‘',
FREE_ELECTIVE: '์ž์œ ์„ ํƒ',
CHAPEL: '์ฑ„ํ”Œ',
} as const;

export type ResultCategoryKey = (typeof RESULT_CATEGORY)[keyof typeof RESULT_CATEGORY];
Loading