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

Thanaphomh/info #29

Merged
merged 5 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions src/lib/components/ImageView/ImageView.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<script lang="ts">
import Fa from 'svelte-fa';
import { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';
import { onMount } from 'svelte';
import { cn } from '$lib/utils';

export let imgUrls: string[] | undefined;

let currentImgIndex = 0;
let imgRefs: HTMLImageElement[] = new Array(imgUrls ? imgUrls.length : 0);

const handleClickLeft = () => {
if (imgUrls) {
currentImgIndex = (currentImgIndex - 1 + imgUrls.length) % imgUrls.length;
}
};
const handleClickRight = () => {
if (imgUrls) {
currentImgIndex = (currentImgIndex + 1 + imgUrls.length) % imgUrls.length;
}
};

// If currentImgIndex is changed, scroll to that image
$: {
if (imgRefs[currentImgIndex]) {
imgRefs[currentImgIndex].scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'start'
});
}
}

// Mark the visible image index to visibleImgIndex
let observer: IntersectionObserver;
let visibleImgIndex = 0;
onMount(() => {
observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const index = imgRefs.indexOf(entry.target as HTMLImageElement);
if (index !== -1) {
visibleImgIndex = index;
}
}
});
},
{
root: null,
threshold: 0.5
}
);

imgRefs.forEach((img) => {
if (img) observer.observe(img);
});

return () => {
observer.disconnect();
};
});

// When scroll end, set currentImgIndex to visibleImgIndex if it was scrolled
const handleScrollEnd = () => {
currentImgIndex = visibleImgIndex;
};
</script>

{#if imgUrls && imgUrls.length >= 0}
<div class="relative w-full">
<div
class="flex flex-row overflow-auto w-full aspect-video snap-x snap-mandatory"
on:scrollend={handleScrollEnd}
role="presentation"
>
{#each imgUrls as imgUrl, index}
<img
bind:this={imgRefs[index]}
src={imgUrl}
alt="img"
class="w-full aspect-video object-cover object-center snap-center"
/>
{/each}
</div>

<button on:click={handleClickLeft} class="absolute left-4 top-1/2 transform -translate-y-1/2">
<Fa icon={faChevronLeft} class="!w-8 !h-8 text-white opacity-70" />
</button>

<button on:click={handleClickRight} class="absolute right-4 top-1/2 transform -translate-y-1/2">
<Fa icon={faChevronRight} class="!w-8 !h-8 text-white opacity-70" />
</button>

<div class="absolute bottom-4 left-1/2 transfrom -translate-x-1/2 flex flex-row gap-2">
{#each imgUrls as _, index}
<div
class={cn(
'w-2 h-2 rounded-full bg-white',
index === currentImgIndex ? 'opacity-70' : 'opacity-30'
)}
/>
{/each}
</div>
</div>
{:else}
<div class="flex flex-col items-center justify-center w-full aspect-video bg-sucu-gray-light">
<span class="text-2xl mt-4">ไม่พบรูปภาพ</span>
</div>
{/if}

<style>
.overflow-auto {
-ms-overflow-style: none; /* Internet Explorer 10+ */
scrollbar-width: none; /* Firefox */
}

.overflow-auto::-webkit-scrollbar {
display: none; /* Safari and Chrome */
}
</style>
2 changes: 2 additions & 0 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import OrganizationCard from '$lib/components/OrganizationCard/OrganizationCard.svelte';
import { mockAnnouncementCard } from '$lib/mock/annoucementCardData';
import { onMount } from 'svelte';
import { goto } from '$app/navigation';
let container: HTMLDivElement;
let activeSlide = 0;
Expand Down Expand Up @@ -76,6 +77,7 @@
'font-semibold px-9 py-2 leading-5',
'max-md:text-xs max-md:leading-3 max-md:px-3 max-md:py-1.5'
)}
on:click={() => goto(`/info`)}
>
รู้จักกับสโมสรนิติฯ
</Button>
Expand Down
34 changes: 34 additions & 0 deletions src/routes/info/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script lang="ts">
import MaxWidthWrapper from '$lib/components/MaxWidthWrapper.svelte';
import { faCircleArrowLeft } from '@fortawesome/free-solid-svg-icons';
import Fa from 'svelte-fa';
import Button from '$lib/components/Button.svelte';
import { cn } from '$lib/utils';
import orgDatas from './orgData';
import { goto } from '$app/navigation';

const pushPath = (path: string) => {
goto(`/info/${path}`);
};
</script>

<MaxWidthWrapper class="flex flex-col flex-grow min-h-screen">
<button on:click={() => history.back()} class="lg:relative -left-14">
<Fa icon={faCircleArrowLeft} size="lg" />
</button>
<div class="flex flex-col items-center gap-52 mb-32">
{#each orgDatas as org, index}
<div class={cn('flex flex-row items-center gap-16', index % 2 == 1 && 'flex-row-reverse')}>
<img src={org.src} alt={org.alt} class="w-52 h-52" />
<div class="flex flex-col gap-9">
<span class="font-bold text-5xl leading-[48px] tracking-[-0.01em]">{org.title}</span>
<span class="text-xl">{org.desc}</span>
<Button
class={cn('w-64 h-14 font-semibold text-2xl text-black', org.buttonColor)}
on:click={() => pushPath(org.subPath)}>{org.buttonText}</Button
>
</div>
</div>
{/each}
</div>
</MaxWidthWrapper>
55 changes: 55 additions & 0 deletions src/routes/info/[org]/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<script lang="ts">
import MaxWidthWrapper from '$lib/components/MaxWidthWrapper.svelte';
import { page } from '$app/stores';
import orgDatas from '../orgData';
import Button from '$lib/components/Button.svelte';
import Fa from 'svelte-fa';
import ImageView from '$lib/components/ImageView/ImageView.svelte';
import { faCircleArrowLeft } from '@fortawesome/free-solid-svg-icons';

let org = $page.params.org;

const orgData = orgDatas.find((orgData) => orgData.subPath === org);

const titleClass = 'font-bold text-[30px] tracking-[-0.01em]';
const textClass = 'text-2xl';
</script>

<MaxWidthWrapper>
<button on:click={() => history.back()} class="lg:relative -left-14">
<Fa icon={faCircleArrowLeft} size="lg" />
</button>
{#if orgData}
<div class="flex flex-col gap-32 mb-32">
<div class="flex flex-row items-center gap-16">
<img src={orgData.src} alt={orgData.alt} class="w-52 h-52" />
<div class="flex flex-col gap-9">
<h2 class="font-bold text-5xl leading-[48px] tracking-[-0.01em]">{orgData.title}</h2>
<span class="text-2xl">{orgData.desc}</span>
</div>
</div>

<div class="flex flex-col gap-12">
<span class={titleClass}>{orgData.shortName} คืออะไร ?</span>
<span class={textClass}>{orgData.whatIs}</span>
</div>

<div class="flex flex-col gap-12">
<span class={titleClass}>หน้าที่ตามระเบียบ</span>
<span class={textClass}>{orgData.duty}</span>
</div>

<div class="flex flex-col gap-12">
<span class={titleClass}>แผนผังองค์กร</span>
<ImageView imgUrls={orgData.images} />
</div>

<div class="flex flex-col gap-8">
<span class={titleClass}>ระเบียบสโมสรนิสิตจุฬาฯ</span>
<Button variant="default" class="w-fit">คลิกเพื่ออ่านระเบียบ</Button>
</div>
</div>
{:else}
<p>Organization data not found.</p>
{/if}
</MaxWidthWrapper>
51 changes: 51 additions & 0 deletions src/routes/info/orgData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import sgcuLOGO from '$lib/assets/images/sgcu.png';
import smoLOGO from '$lib/assets/images/smo.png';
import sapaLOGO from '$lib/assets/images/sapanisit.png';
import testImg1 from '$lib/assets/images/picslide1.jpg';
import testImg2 from '$lib/assets/images/picslide2.jpg';

const tempText =
'Seventeen เป็นวงบอยกรุ๊ปจากค่าย Pledis Entertainment เดบิวต์เมื่อวันที่ 26 พฤษภาคม 2015 ประกอบด้วยสมาชิก 13 คน แบ่งออกเป็น 3 กลุ่มย่อย (Unit) ได้แก่ กลุ่มฮิปฮอป (Hip Hop Unit) กลุ่มเสียงร้อง (Vocal Unit) และกลุ่มการแสดง (Performance Unit) สาเหตุที่ตั้งชื่อวงว่า Seventeen ทั้ง ๆ ที่มีสมาชิกแค่ 13 คน ก็เพราะชื่อวงนี้มีคอนเซ็ปต์มาจากการรวมตัวของสมาชิก ทั้ง 13 คน กลุมย่อย 3 กลุ่ม จนกลายเป็น 1 ทีม คือ 17 หรือ Seventeen นั่นเอง';

const orgDatas = [
{
src: smoLOGO,
alt: 'SMO Logo',
title: 'สโมสรนิสิตจุฬาลงกรณ์มหาวิทยาลัย',
desc: tempText,
buttonText: 'รู้จักสโมสรนิสิตฯ',
buttonColor: 'bg-sucu-pink-05',
subPath: 'smo',
shortName: 'สโมสรนิสิตจุฬาฯ',
whatIs: tempText,
duty: tempText,
images: [testImg1, testImg2]
},
{
src: sgcuLOGO,
alt: 'SGCU Logo',
title: 'องค์การบริหารสโมสรนิสิต จุฬาลงกรณ์มหาวิทยาลัย (อบจ.)',
desc: tempText,
buttonText: 'รู้จัก อบจ.',
buttonColor: 'bg-sucu-pink-03',
subPath: 'sgcu',
shortName: 'อบจ.',
whatIs: tempText,
duty: tempText,
images: [testImg1, testImg2, testImg1, testImg2, testImg1, testImg2]
},
{
src: sapaLOGO,
alt: 'Sapanisit Logo',
title: 'สภานิสิตจุฬาลงกรณ์มหาวิทยาลัย',
desc: tempText,
buttonText: 'รู้จักสภานิสตฯ',
buttonColor: 'bg-sucu-pink-02',
subPath: 'sapa',
shortName: 'สภานิสิต',
whatIs: tempText,
duty: tempText
}
];

export default orgDatas;
Loading