Skip to content

Commit

Permalink
Merge pull request #19 from isd-sgcu/macgeargear/sucu-69-page-document
Browse files Browse the repository at this point in the history
Macgeargear/sucu 69 page document
  • Loading branch information
macgeargear authored Sep 20, 2024
2 parents 5ed6f0c + 69d1390 commit 20a876b
Show file tree
Hide file tree
Showing 11 changed files with 389 additions and 11 deletions.
17 changes: 8 additions & 9 deletions src/lib/components/List/List.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,23 @@
<a
href={linkHref}
target="_blank"
class={`h-auto w-full flex flex-col py-3 px-4 rounded ${listVariants({ variant })}`}
class={cn(
'h-auto w-full flex flex-col py-3 px-4',
listVariants({ variant }),
'hover:bg-sucu-pink-05'
)}
>
<div
class={cn(
'text-ellipsis whitespace-nowrap overflow-hidden',
typography({ variant: 'body-large' }),
`max-md:${typography({ variant: 'body-normal' })}`
typography({ variant: 'body-normal' }),
'md:text-2xl'
)}
>
{title}
</div>

<div
class={cn(
`max-md:${typography({ variant: 'body-small' })}`,
typography({ variant: 'body-normal' })
)}
>
<div class={cn(typography({ variant: 'body-small' }), 'md:text-base')}>
{formatDate(createdAt)} โดย {createdBy}
</div>
</a>
15 changes: 15 additions & 0 deletions src/lib/components/MaxWidthWrapper.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script lang="ts">
import { cn } from '$lib/utils';
export let className: string = '';
export { className as class };
</script>

<div
class={cn(
'h-full mx-auto w-full max-w-screen-xl px-6 lg:px-[200px] mt-6 lg:mt-[72px]',
className
)}
>
<slot />
</div>
91 changes: 91 additions & 0 deletions src/lib/mock/document.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { DocumentType, Role, type Document, type User } from '$lib/types';
import dayjs from 'dayjs';
import buddhistEra from 'dayjs/plugin/buddhistEra';

dayjs.extend(buddhistEra);
export // * mock data
const created_at_1 = '2022-01-01';
const created_at_2 = '2023-01-01';
const created_at_3 = '2024-01-01';
const created_at_4 = '2025-01-01';
const updated_at = '2030-02-01';

const sgcu_admin: User = {
id: '6000000000',
first_name: 'Admin',
last_name: 'Admin',
role: Role.SGCU_SUPERADMIN,
created_at: created_at_1,
updated_at
};
const sccu_admin: User = {
id: '6000000001',
first_name: 'Admin',
last_name: 'Admin',
role: Role.SCCU_SUPERADMIN,
created_at: created_at_2,
updated_at
};

export const documents: Document[] = [
{
id: 'DOC-09649054',
title: 'เอกสารลับจากดัมเบิลดอร์',
content: 'เนื้อหาของเอกสารลับจากดัมเบิลดอร์',
user_id: sgcu_admin.id,
type_id: DocumentType.ANNOUNCEMENT,
created_at: created_at_3,
updated_at,
author: sgcu_admin
},
{
id: 'DOC-09649055',
title: 'ประกาศรับสมัครคณะกรรมาธิการวิสามัญพิจารณางบประมาณสโมสรนิสิต 00',
content: 'เนื้อหาของประกาศรับสมัครคณะกรรมาธิการวิสามัญพิจารณางบประมาณสโมสรนิสิต',
user_id: sccu_admin.id,
type_id: DocumentType.ANNOUNCEMENT,
created_at: created_at_4,
updated_at,
author: sccu_admin
},
{
id: 'DOC-09649056',
title: 'ประกาศรับสมัครคณะกรรมาธิการวิสามัญพิจารณางบประมาณสโมสรนิสิต 01',
content: 'เนื้อหาของประกาศรับสมัครคณะกรรมาธิการวิสามัญพิจารณางบประมาณสโมสรนิสิต',
user_id: sgcu_admin.id,
type_id: DocumentType.ANNOUNCEMENT,
created_at: created_at_4,
updated_at,
author: sgcu_admin
},
{
id: 'DOC-09649056',
title: 'ประกาศรับสมัครคณะกรรมาธิการวิสามัญพิจารณางบประมาณสโมสรนิสิต 02',
content: 'เนื้อหาของประกาศรับสมัครคณะกรรมาธิการวิสามัญพิจารณางบประมาณสโมสรนิสิต',
user_id: sccu_admin.id,
type_id: DocumentType.BUDGET,
created_at: created_at_1,
updated_at,
author: sccu_admin
},
{
id: 'DOC-09649058',
title: 'ประกาศรับสมัครคณะกรรมาธิการวิสามัญพิจารณางบประมาณสโมสรนิสิต 03',
content: 'เนื้อหาของประกาศรับสมัครคณะกรรมาธิการวิสามัญพิจารณางบประมาณสโมสรนิสิต',
user_id: sccu_admin.id,
type_id: DocumentType.STATISTIC,
created_at: created_at_1,
updated_at,
author: sgcu_admin
},
{
id: 'DOC-09649060',
title: 'ประกาศรับสมัครคณะกรรมาธิการวิสามัญพิจารณางบประมาณสโมสรนิสิต 04',
content: 'เนื้อหาของประกาศรับสมัครคณะกรรมาธิการวิสามัญพิจารณางบประมาณสโมสรนิสิต',
user_id: sccu_admin.id,
type_id: DocumentType.STATISTIC,
created_at: created_at_1,
updated_at,
author: sgcu_admin
}
];
23 changes: 23 additions & 0 deletions src/lib/types/document.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { User } from './user';

export type Document = {
id: string;
title: string;
content: string;
banner?: string;
cover?: string;
user_id: string;
type_id: string;
created_at: string;
updated_at: string;

author: User;
// images: Attachment[];
// docs: Attachment[];
};

export enum DocumentType {
ANNOUNCEMENT = 'ANNOUNCEMENT',
BUDGET = 'BUDGET',
STATISTIC = 'STATISTIC'
}
3 changes: 3 additions & 0 deletions src/lib/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './document';
export * from './role';
export * from './user';
6 changes: 6 additions & 0 deletions src/lib/types/role.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export enum Role {
SGCU_ADMIN = 'SGCU_ADMIN',
SGCU_SUPERADMIN = 'SGCU_SUPERADMIN',
SCCU_ADMIN = 'SCCU_ADMIN',
SCCU_SUPERADMIN = 'SCCU_SUPERADMIN'
}
10 changes: 10 additions & 0 deletions src/lib/types/user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { Role } from './role';

export type User = {
id: string;
first_name: string;
last_name: string;
role: Role;
created_at: string;
updated_at: string;
};
176 changes: 176 additions & 0 deletions src/routes/document/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
<script lang="ts">
import { cn } from '$lib/utils';
import { faCircleArrowLeft } from '@fortawesome/free-solid-svg-icons';
import { typography } from '../../styles/tailwind/typography';
import Fa from 'svelte-fa';
import TabsRoot from '$lib/components/Tabs/TabsRoot.svelte';
import TabsList from '$lib/components/Tabs/TabsList.svelte';
import TabsTrigger from '$lib/components/Tabs/TabsTrigger.svelte';
import TabsContent from '$lib/components/Tabs/TabsContent.svelte';
import MaxWidthWrapper from '$lib/components/MaxWidthWrapper.svelte';
import SearchBar from '$lib/components/SearchBar.svelte';
import { Role, type Document } from '$lib/types';
import Dropdown from '$lib/components/Dropdown/Dropdown.svelte';
import DocumentList from './DocumentList.svelte';
import TabCapsule from '$lib/components/TabCapsule.svelte';
export let data;
const { documents } = data;
let searchValue = '';
let dropdownValue = 'All';
let years = Array.from(new Set(documents.map((doc) => new Date(doc.created_at).getFullYear())))
.sort((a, b) => b - a)
.map(String);
let paginatedAll: Document[] = [];
let paginatedSGCU: Document[] = [];
let paginatedSCCU: Document[] = [];
let currentPages = {
all: 1,
sgcu: 1,
sccu: 1
};
const documentsPerPage = 3;
$: totalPages = {
all: Math.ceil(filteredDocuments('all').length / documentsPerPage),
sgcu: Math.ceil(filteredDocuments('sgcu').length / documentsPerPage),
sccu: Math.ceil(filteredDocuments('sccu').length / documentsPerPage)
};
$: {
paginatedAll = paginate(filteredDocuments('all'), currentPages.all, documentsPerPage);
paginatedSGCU = paginate(filteredDocuments('sgcu'), currentPages.sgcu, documentsPerPage);
paginatedSCCU = paginate(filteredDocuments('sccu'), currentPages.sccu, documentsPerPage);
searchValue = searchValue;
dropdownValue = dropdownValue;
}
const filteredDocuments = (tab: 'all' | 'sgcu' | 'sccu') => {
let filteredDocs = documents;
const filterRole = (authorRole: string, docRole: Role) => {
return authorRole.split('_')[0] === docRole.split('_')[0];
};
if (searchValue) {
filteredDocs = filteredDocs.filter((doc) =>
doc.title.toLowerCase().includes(searchValue.toLowerCase())
);
}
if (dropdownValue && dropdownValue !== 'All') {
filteredDocs = filteredDocs.filter((doc) => {
const year = new Date(doc.created_at).getFullYear().toString();
return year === dropdownValue;
});
}
switch (tab) {
case 'sgcu':
filteredDocs = filteredDocs.filter((doc) => filterRole(doc.author.role, Role.SGCU_ADMIN));
break;
case 'sccu':
filteredDocs = filteredDocs.filter((doc) => filterRole(doc.author.role, Role.SCCU_ADMIN));
break;
}
return filteredDocs;
};
function paginate(docs: Document[], currentPage: number, documentsPerPage: number) {
const start = (currentPage - 1) * documentsPerPage;
const end = currentPage * documentsPerPage;
return docs.slice(start, end);
}
function changePage(tab: 'all' | 'sgcu' | 'sccu', direction: 'next' | 'prev') {
const page = currentPages[tab];
const totalPage = totalPages[tab];
if (direction === 'next' && page < totalPage) {
currentPages[tab]++;
} else if (direction === 'prev' && page > 1) {
currentPages[tab]--;
}
}
let selectedTabs: string[] = [];
let tags = ['สภานิสิตฯ', 'สำนักเลขาธิการ', 'กมธ. สามัญ', 'กมธ. วิสามัญ'];
let tabCapsules = tags.map((label) => ({ label, active: false }));
function toggle(index: number) {
tabCapsules = tabCapsules.map((tab, i) =>
i === index ? { ...tab, active: !tab.active } : tab
);
const tab = tabCapsules[index];
selectedTabs = tab.active
? [...selectedTabs, tab.label]
: selectedTabs.filter((label) => label !== tab.label);
}
</script>

<MaxWidthWrapper class="mt-10 space-y-12">
<div class="flex flex-col gap-3 items-start">
<div class="flex items-center gap-4">
<button on:click={() => history.back()} class="lg:relative -left-60 top-2">
<Fa icon={faCircleArrowLeft} size="lg" />
</button>
<h1 class={cn(typography({ variant: 'heading3' }), 'md:text-5xl lg:order-first')}>เอกสาร</h1>
</div>
<p class="text-sucu-gray lg:w-full">
เอกสารทั้งหมดในนามสโมสรนิสิตจุฬาฯ อบจ. และสภานิสิตจุฬาฯ ซึ่งเปิดเผยให้นิสิตได้อ่านโดยทั่วกัน
</p>
</div>

<SearchBar bind:value={searchValue} />

<TabsRoot defaultActiveTab="all">
<TabsList>
<TabsTrigger value="all">ทั้งหมด</TabsTrigger>
<TabsTrigger value="sgcu">อบจ.</TabsTrigger>
<TabsTrigger value="sccu">สภานิสิต</TabsTrigger>
</TabsList>
<Dropdown
items={['All', ...years]}
bind:currentChoice={dropdownValue}
outerClass="w-64 my-12"
/>
<div class="flex flex-wrap items-center gap-2 my-12">
{#each tabCapsules as tab, i}
<TabCapsule active={tab.active} label={tab.label} on:click={() => toggle(i)} />
{/each}
</div>

<TabsContent value="all" class="space-y-2">
<DocumentList
currentPage={currentPages.all}
changePage={(variant, direction) => changePage(variant, direction)}
documents={paginatedAll}
totalPages={totalPages.all}
variantKey="all"
/>
</TabsContent>

<TabsContent value="sgcu" class="space-y-2">
<DocumentList
currentPage={currentPages.sgcu}
changePage={(variant, direction) => changePage(variant, direction)}
documents={paginatedSGCU}
totalPages={totalPages.sgcu}
variantKey="sgcu"
/>
</TabsContent>

<TabsContent value="sccu" class="space-y-2">
<DocumentList
currentPage={currentPages.sccu}
changePage={(variant, direction) => changePage(variant, direction)}
documents={paginatedSCCU}
totalPages={totalPages.sccu}
variantKey="sccu"
/>
</TabsContent>
</TabsRoot>
</MaxWidthWrapper>
9 changes: 9 additions & 0 deletions src/routes/document/+page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { PageLoad } from './$types';
import 'dayjs/locale/th';
import { documents } from '$lib/mock/document';

export const load: PageLoad = async () => {
return {
documents
};
};
Loading

0 comments on commit 20a876b

Please sign in to comment.