Skip to content

Commit 8f911a6

Browse files
committed
feat(5): create vote card
1 parent c6cf2dd commit 8f911a6

7 files changed

Lines changed: 143 additions & 4 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
},
2626
"dependencies": {
2727
"@sveltejs/adapter-static": "^2.0.3",
28+
"dayjs": "^1.11.10",
2829
"scrollama": "^3.2.0"
2930
},
3031
"devDependencies": {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script lang="ts">
2+
import type { Hst } from '@histoire/plugin-svelte';
3+
import VoteCard from './VoteCard.svelte';
4+
import { failedVoting } from '../../mocks/data/voting';
5+
export let Hst: Hst;
6+
</script>
7+
8+
<Hst.Story title="VoteCard">
9+
<VoteCard voting={failedVoting} />
10+
</Hst.Story>
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<script lang="ts">
2+
import { DefaultVotingResult, type Voting } from '$models/voting';
3+
import { Tag } from 'carbon-components-svelte';
4+
import dayjs from 'dayjs';
5+
import 'dayjs/locale/th';
6+
import buddhistEra from 'dayjs/plugin/buddhistEra';
7+
import { failedVoting, failedVotingSummary } from '../../mocks/data/voting';
8+
9+
dayjs.extend(buddhistEra);
10+
dayjs.locale('th');
11+
12+
type VoteCardTheme = {
13+
bg: string;
14+
hoveredBg: string;
15+
tagBg: string;
16+
tagFontColor: string;
17+
};
18+
const CARD_THEMES: Record<DefaultVotingResult, VoteCardTheme> = {
19+
[DefaultVotingResult.Passed]: {
20+
bg: 'bg-teal-10',
21+
hoveredBg: 'hover:bg-teal-20',
22+
tagBg: 'bg-teal-30',
23+
tagFontColor: 'text-text-01'
24+
},
25+
[DefaultVotingResult.Failed]: {
26+
bg: 'bg-red-10',
27+
hoveredBg: 'hover:bg-red-20',
28+
tagBg: 'bg-red-30',
29+
tagFontColor: 'text-text-01'
30+
}
31+
};
32+
const CANDIDATE_CARD_THEME: VoteCardTheme = {
33+
bg: 'bg-purple-10',
34+
hoveredBg: 'hover:bg-purple-20',
35+
tagBg: 'bg-purple-70',
36+
tagFontColor: 'text-white'
37+
};
38+
39+
export let voting: Voting = {} as Voting;
40+
41+
const { totalCount, totalAmount } = failedVotingSummary.reduce(
42+
(acc, assembly) => {
43+
return {
44+
totalCount: acc.totalCount + assembly.count,
45+
totalAmount: acc.totalAmount + assembly.total
46+
};
47+
},
48+
{ totalCount: 0, totalAmount: 0 }
49+
);
50+
51+
$: theme = CARD_THEMES[voting.result as DefaultVotingResult] || CANDIDATE_CARD_THEME;
52+
$: isCandidate = ![DefaultVotingResult.Failed, DefaultVotingResult.Passed].includes(
53+
voting.result as DefaultVotingResult
54+
);
55+
</script>
56+
57+
<div
58+
class={`vote-card relative p-4 flex flex-col gap-y-2 w-72 h-64.5 ${theme.bg} ${theme.hoveredBg}`}
59+
>
60+
<p class="text-02">{dayjs(voting.date).format('D MMM BB')}</p>
61+
<a
62+
class="vote-card--url after:inset text-text-01 text-xl font-[700] no-underline after:absolute w-56"
63+
href={voting.sourceUrl}
64+
>
65+
{voting.title}
66+
</a>
67+
<section class="vote-card__result flex flex-col gap-y-2 w-56">
68+
<Tag class={`${theme.tagFontColor} ${theme.tagBg} w-fit m-0`}>{voting.result}</Tag>
69+
<div>
70+
<div class="flex align-middle justify-between">
71+
<p class="text-text-01 font-[600]">{isCandidate ? voting.result : 'เห็นด้วย'}</p>
72+
<p>
73+
<span class="mr-[2px] text-text-primary font-[600]">{totalCount}</span>
74+
<span class="text-text-02">/{totalAmount}</span>
75+
</p>
76+
</div>
77+
<ul class="vote-card__result--list">
78+
{#each failedVotingSummary as assembly}
79+
<li class="vote-card__result--item flex flex-row align-middle justify-between">
80+
<p>{assembly.name}</p>
81+
<p>
82+
<span class="mr-[2px] text-text-primary">{assembly.count}</span>
83+
<span class="text-text-02">/{assembly.total}</span>
84+
</p>
85+
</li>
86+
{/each}
87+
</ul>
88+
</div>
89+
</section>
90+
</div>
91+
92+
<style lang="scss">
93+
.vote-card {
94+
position: relative;
95+
96+
&--url {
97+
&::after {
98+
content: '';
99+
position: absolute;
100+
inset: 0;
101+
}
102+
}
103+
}
104+
</style>

src/mocks/data/voting.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,20 @@ export const failedVoting: Voting = {
4848
...passedVoting,
4949
result: DefaultVotingResult.Failed
5050
};
51+
52+
export const candidateVoting: Voting = {
53+
...passedVoting,
54+
result: 'ชื่อแคนดิเดต'
55+
};
56+
57+
export const passedVotingSummary = [
58+
{ name: 'สส. ฝ่ายรัฐบาล', count: 160, total: 315 },
59+
{ name: 'สส. ฝ่ายค้าน', count: 164, total: 185 },
60+
{ name: 'สว.', count: 200, total: 250 }
61+
];
62+
63+
export const failedVotingSummary = [
64+
{ name: 'สส. ฝ่ายรัฐบาล', count: 16, total: 315 },
65+
{ name: 'สส. ฝ่ายค้าน', count: 4, total: 185 },
66+
{ name: 'สว.', count: 20, total: 250 }
67+
];

src/routes/politicians/[id]/+page.svelte

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
<script lang="ts">
2-
import SideNav from '../../../components/politicians/SideNav.svelte';
2+
import SideNav from '$components/politicians/SideNav.svelte';
33
4+
import Share from '$components/Share/Share.svelte';
45
import General from '$components/icons/GeneralIcon.svelte';
56
import Politician from '$components/icons/PoliticianIcon.svelte';
67
import Vote from '$components/icons/VoteIcon.svelte';
78
import PartyDetail from '$components/politicians/PartyDetail.svelte';
89
import PositionStatus from '$components/politicians/PositionStatus.svelte';
910
import Section from '$components/politicians/Section.svelte';
10-
import Share from '$components/Share/Share.svelte';
1111
import VotingResultTag from '$components/politicians/VotingResultTag.svelte';
1212
import { Breadcrumb, BreadcrumbItem, Button, InlineNotification } from 'carbon-components-svelte';
1313
import ArrowRight from 'carbon-icons-svelte/lib/ArrowRight.svelte';
1414
import ArrowUpRight from 'carbon-icons-svelte/lib/ArrowUpRight.svelte';
15-
import Download from 'carbon-icons-svelte/lib/Download.svelte';
16-
import TableSplit from 'carbon-icons-svelte/lib/TableSplit.svelte';
1715
import scrollama from 'scrollama';
1816
import { onMount } from 'svelte';
1917
2018
import DownloadData from '$components/DownloadData/DownloadData.svelte';
19+
import VoteCard from '$components/votes/VoteCard.svelte';
20+
import { passedVoting } from '../../../mocks/data/voting';
2121
2222
export let data;
2323
const { politician, agreedVoting, disagreedVoting, votingAbsentStats, totalProposedBill } = data;
@@ -131,6 +131,7 @@
131131
absentTotal={votingAbsentStats.absentVoting}
132132
/>
133133
<div class="flex-1 flex flex-col gap-6 w-full min-w-0">
134+
<VoteCard voting={passedVoting} />
134135
<Section id="personal" title="ข้อมูลพื้นฐาน">
135136
<General slot="icon" size="32" />
136137
<div>

tailwind.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export default {
4646
'text-02': '#6F6F6F',
4747
'text-03': '#A8A8A8',
4848
'text-04': '#FFFFFF',
49+
'text-primary': '#161616',
4950
'text-error': '#C72502',
5051
'decorative-01': '#E0E0E0',
5152
'ui-01': '#F4F4F4',

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,6 +1541,11 @@ data-urls@^3.0.2:
15411541
whatwg-mimetype "^3.0.0"
15421542
whatwg-url "^11.0.0"
15431543

1544+
dayjs@^1.11.10:
1545+
version "1.11.10"
1546+
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0"
1547+
integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==
1548+
15441549
debug@2.6.9:
15451550
version "2.6.9"
15461551
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"

0 commit comments

Comments
 (0)