Skip to content

Commit 34b942b

Browse files
JongSinisterpatthapolkitleomotors
authored
Feat/UI/course card (#721)
* add course-card and recommended-tag * format course card code * add mobile course-card & stories * add recommended-tag storybook * format autofix --------- Co-authored-by: Patthapol Kittikun <patthapol.k@gmail.com> Co-authored-by: Nutthapat Pongtanyavichai <contact@leomotors.me>
1 parent c2d6e50 commit 34b942b

File tree

7 files changed

+200
-0
lines changed

7 files changed

+200
-0
lines changed

apps/web/src/routes/+page.svelte

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
<script lang="ts">
22
import { Button } from '@repo/ui/button'
33
import { Chip } from '@repo/ui/chip'
4+
import { CourseCard } from '@repo/ui/course-card'
45
import { DayChip } from '@repo/ui/day-chip'
56
import { GenedChip } from '@repo/ui/gened-chip'
67
import { Input } from '@repo/ui/input'
8+
import { RecommendedTag } from '@repo/ui/recommended-tag'
79
810
let counter = 0
911
@@ -33,3 +35,9 @@
3335
>
3436
<DayChip day="SA" />
3537
<GenedChip type="SC" />
38+
39+
<h1>Testtsetst</h1>
40+
<CourseCard recommended="{true}" class="mt-4" />
41+
42+
<h1>RecommendedTag</h1>
43+
<RecommendedTag />
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<script context="module" lang="ts">
2+
import type { Meta } from '@storybook/svelte'
3+
4+
import { CourseCard } from './index.js'
5+
6+
export const meta = {
7+
title: 'Molecule/CourseCard',
8+
component: CourseCard,
9+
tags: ['autodocs'],
10+
argTypes: {
11+
selected: {
12+
control: 'boolean',
13+
},
14+
recommended: {
15+
control: 'boolean',
16+
},
17+
onButtonClick: {
18+
action: 'onButtonClick',
19+
},
20+
class: {
21+
control: false,
22+
},
23+
course: {
24+
control: false,
25+
},
26+
},
27+
} satisfies Meta<CourseCard>
28+
</script>
29+
30+
<script lang="ts">
31+
import { Story, Template } from '@storybook/addon-svelte-csf'
32+
</script>
33+
34+
<!--👇 We create a “template” of how args map to rendering-->
35+
<Template let:args>
36+
<CourseCard {...args} />
37+
</Template>
38+
39+
<!--👇 Each story then reuses that template-->
40+
<Story name="Default" />
41+
42+
<Story name="Recommended" args="{{ recommended: true }}" />
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<script lang="ts">
2+
import { Check, Dot, Plus } from 'lucide-svelte'
3+
4+
import { cn } from '../../utils'
5+
import { Button } from '../button'
6+
import { DayChip } from '../day-chip'
7+
import { GenedChip } from '../gened-chip'
8+
import { RecommendedTag } from '../recommended-tag'
9+
10+
let className: string | undefined | null = undefined
11+
export { className as class }
12+
13+
export let course: {
14+
code: string
15+
name: string
16+
credit: number
17+
gened: ('HU' | 'SC' | 'SO' | 'IN')[]
18+
seat: number
19+
maxseat: number
20+
review: number
21+
days: ('MO' | 'TU' | 'WE' | 'TH' | 'FR' | 'SA' | 'SU')[]
22+
} = {
23+
code: '0123101',
24+
name: 'PARAGRAPH WRITING',
25+
credit: 3,
26+
gened: ['HU'],
27+
seat: 24,
28+
maxseat: 305,
29+
review: 14,
30+
days: ['MO', 'TU', 'WE'],
31+
}
32+
33+
export let selected: boolean = false
34+
export let recommended: boolean = false
35+
36+
export const onButtonClick = () => {
37+
selected = !selected
38+
}
39+
</script>
40+
41+
<div
42+
class="{cn(
43+
'flex flex-col w-[334px] h-[170px] lg:w-[440px] lg:h-[200px] ring-2 ring-neutral-100 rounded-xl py-5 px-4 lg:p-6 justify-between relative',
44+
className,
45+
)}"
46+
{...$$restProps}
47+
>
48+
{#if recommended}
49+
<RecommendedTag class="absolute top-[-9.5px] left-0" />
50+
{/if}
51+
<div class="flex flex-row justify-between items-center">
52+
<div class="flex flex-col">
53+
<div class="font-medium text-caption">{course.code}</div>
54+
<div class="font-medium text-subtitle">{course.name}</div>
55+
</div>
56+
<div class="flex gap-1">
57+
{#each course.gened as gened}
58+
<GenedChip type="{gened}" />
59+
{/each}
60+
</div>
61+
</div>
62+
<div class="flex flex-col gap-2">
63+
<div
64+
class="font-normal text-caption text-neutral-400 flex flex-row items-center"
65+
>
66+
{course.credit} หน่วยกิต <Dot color="#EDEDF1" /> ที่นั่ง GenEd {course.seat}
67+
/
68+
{course.maxseat}
69+
<Dot color="#EDEDF1" />
70+
{course.review} รีวิว
71+
</div>
72+
<div class="flex gap-2">
73+
{#each course.days as day}
74+
<DayChip {day} />
75+
{/each}
76+
</div>
77+
</div>
78+
<div class="flex flex-row justify-between items-center">
79+
<Button variant="outlined" size="lg" color="neutral" class="w-36 lg:w-48"
80+
>เลือกเซคชัน</Button
81+
>
82+
{#if !selected}
83+
<Button
84+
variant="outlined"
85+
color="primary"
86+
on:click="{onButtonClick}"
87+
class="w-36 lg:w-48"
88+
>
89+
เลือก <Plus size="16" strokeWidth="3" />
90+
</Button>
91+
{:else}
92+
<Button color="primary" on:click="{onButtonClick}" class="w-36 lg:w-48">
93+
เลือก <Check size="16" strokeWidth="3" />
94+
</Button>
95+
{/if}
96+
</div>
97+
</div>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as CourseCard } from './course-card.svelte'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as RecommendedTag } from './recommended-tag.svelte'
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<script context="module" lang="ts">
2+
import type { Meta } from '@storybook/svelte'
3+
4+
import { RecommendedTag } from './index.js'
5+
6+
export const meta = {
7+
title: 'Atom/RecommendedTag',
8+
component: RecommendedTag,
9+
tags: ['autodocs'],
10+
argTypes: {
11+
class: {
12+
control: false,
13+
},
14+
},
15+
} satisfies Meta<RecommendedTag>
16+
</script>
17+
18+
<script lang="ts">
19+
import { Story, Template } from '@storybook/addon-svelte-csf'
20+
</script>
21+
22+
<!--👇 We create a “template” of how args map to rendering-->
23+
<Template let:args>
24+
<RecommendedTag {...args} />
25+
</Template>
26+
27+
<!--👇 Each story then reuses that template-->
28+
<Story name="Default" />
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<script lang="ts">
2+
import { Sparkles } from 'lucide-svelte'
3+
4+
import { cn } from '../../utils'
5+
6+
let className: string | undefined | null = undefined
7+
8+
export { className as class }
9+
</script>
10+
11+
<div
12+
class="{cn(
13+
'inline-flex items-center justify-center relative text-neutral-white bg-tangerine-500 py-[2px] px-6 rounded-tl-xl rounded-br-xl z-30',
14+
className,
15+
)}"
16+
{...$$restProps}
17+
>
18+
<Sparkles class="mr-2" size="16" />
19+
แนะนำสำหรับคุณ
20+
<div
21+
class="absolute right-0 top-0 translate-x-full border-b-8 border-b-tangerine-700 border-r-8 border-r-neutral-white"
22+
></div>
23+
</div>

0 commit comments

Comments
 (0)