Skip to content
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "kmitl-x",
"description": "Transform KMITL Student Information System UI/UX with enhanced features for a better experience.",
"version": "2.0.1",
"version": "2.0.2",
"license": "MIT",
"type": "module",
"scripts": {
Expand Down
16 changes: 8 additions & 8 deletions src/libs/components/scheduleTable/CardSubject.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,25 @@
export let subject: ScheduleI;
</script>

<div
class=" dark:bg-orange-500/10 bg-orange-100/50 border-l-2 dark:border-orange-400 border-orange-200 px-3 py-1 h-full flex flex-col justify-between rounded
hover:border-orange-500 dark:hover:border-orange-600 transition-all dark:text-orange-300 text-black"
<div
class="min-w-0 dark:bg-orange-500/10 bg-orange-100/50 border-l-2 dark:border-orange-400 border-orange-200 px-3 py-1 h-full flex flex-col justify-between rounded
hover:border-orange-500 dark:hover:border-orange-600 transition-all dark:text-orange-300 text-black overflow-hidden"
>
<div class="flex justify-between text-xs opacity-65 z-10">
<p>{subject.time.type}</p>
<p class="whitespace-nowrap">
<p class="truncate">{subject.time.type}</p>
<p class="whitespace-nowrap truncate">
{subject.time.start} -
{subject.time.end}
</p>
</div>
<h3 class="text-orange-400 text-left text-sm">{subject.name}</h3>
<h3 class="text-orange-400 text-left text-sm truncate">{subject.name}</h3>
<div class="flex justify-between text-xs opacity-65">
<p class="whitespace-nowrap">
<p class="whitespace-nowrap truncate">
section({subject.time.type == "ทฤษฏี"
? subject.theory
: subject.practice})
</p>
<p class="whitespace-nowrap">
<p class="whitespace-nowrap truncate">
{subject.building}
{subject.room == "" ? "" : `( ${subject.room} )`}
</p>
Expand Down
56 changes: 45 additions & 11 deletions src/libs/components/scheduleTable/ScheduleTable.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import type { ScheduleI } from "../../types";
import CardSubject from "./CardSubject.svelte";

export let schedule: Array<ScheduleI>;
export let schedule: Array<ScheduleI>
export let startHourProp: number | null = null;
export let endHourProp: number | null = null;

const days = [
{ name: "Mon", code: "จ." },
Expand All @@ -16,16 +18,48 @@
];

const formatTime = (hour: number) => `${hour.toString().padStart(2, "0")}:00`;

const timeInterval = 15;
const deriveRange = (data: Array<ScheduleI>) => {
const defaultStart = 8;
const defaultEnd = 19;
if (!data || data.length === 0) return { startHour: defaultStart, endHour: defaultEnd };
let min = Infinity;
let max = -Infinity;
for (const s of data) {
const [sh, sm] = s.time.start.split(":").map(Number);
const [eh, em] = s.time.end.split(":").map(Number);
const startMinutes = sh * 60 + (sm || 0);
const endMinutes = eh * 60 + (em || 0);
if (startMinutes < min) min = startMinutes;
if (endMinutes > max) max = endMinutes;
}

const startHour = Math.min(defaultStart, Math.floor(min / 60));
const endHour = Math.max(defaultEnd, Math.ceil(max / 60));
return { startHour, endHour };
};

let startHour = 8;
let endHour = 20;

$: {
const range = deriveRange(schedule ?? []);
startHour = startHourProp ?? range.startHour;
endHour = endHourProp ?? range.endHour;
}

const colsPerHour = Math.round(60 / timeInterval);
</script>

<div>
<table class="w-full rounded-2xl" cellspacing={44}>
<table class="w-full rounded-2xl border-collapse table-fixed">
<thead>
<tr>
<th></th>
{#each Array.from({ length: 20 - 8 }, (_, i) => i + 8) as hour}
{#if hour < 20 - 1}
<th class="border-x dark:border-orange-100/10 border-orange-100 w-[8.33%]" colspan="4">
<th class="w-12 pr-2"></th>
{#each Array.from({ length: endHour - startHour }, (_, i) => i + startHour) as hour}
{#if hour < endHour}
<th class="border-x dark:border-orange-100/10 border-orange-100" colspan={colsPerHour}>
{`${formatTime(hour)} - ${formatTime(hour + 1)}`}
</th>
{/if}
Expand All @@ -36,15 +70,15 @@
{#each days as day}
<tr class="hover:bg-orange-100/20 dark:hover:bg-orange-100/5 group">
<td
class="text-right font-semibold text-sm dark:text-orange-400 text-orange-300 whitespace-nowrap group-hover:scale-125 group-hover:text-orange-400 dark:group-hover:text-orange-600 transition-all"
class="text-right font-semibold text-sm dark:text-orange-400 text-orange-300 whitespace-nowrap group-hover:scale-125 group-hover:text-orange-400 dark:group-hover:text-orange-600 transition-all pl-0 pr-2"
>
{day.name}
</td>
{#each createTimeSlot(schedule, day.code) as slot}
{#each createTimeSlot(schedule, day.code, startHour, endHour, timeInterval) as slot}
{#if slot == undefined}
<td class="border-x dark:border-orange-100/10 border-orange-100"></td>
<td class="border-x dark:border-orange-100/10 border-orange-100 min-w-0"></td>
{:else}
<td colspan={slot.colSpan}>
<td class="min-w-0" colspan={slot.colSpan}>
<CardSubject subject={slot} />
</td>
{/if}
Expand All @@ -60,6 +94,6 @@
@apply font-prompt font-normal whitespace-nowrap text-orange-400;
}
td {
@apply font-prompt w-[2.22%] p-1 h-28;
@apply font-prompt p-1 h-28;
}
</style>
79 changes: 45 additions & 34 deletions src/libs/utils/StudentHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,45 +24,56 @@ const downloadBlob = (blob: Blob, name = "file.txt") => {
};
const createTimeSlot = (
schedule: ScheduleI[],
day: string = "จ."
day: string = "จ.",
startHour: number = 8,
endHour: number = 19,
timeInterval: number = 15
): Array<undefined | (ScheduleI & { colSpan: number })> => {
const timeSlot = [];
const timeSlot: Array<undefined | (ScheduleI & { colSpan: number })> = [];
const findDay = schedule.filter((item) => item.time.day == day);
let colSlot = 44;
const startTime = 8 * 60;
const timeInterval = 15;
for (let i = 0; colSlot > i; i++) {
const currentTime = startTime + i * timeInterval;
const hours = Math.floor(currentTime / 60);
const minutes = currentTime % 60;
const formattedTime = `${String(hours).padStart(2, "0")}:${String(
minutes
).padStart(2, "0")}`;
const findTime = findDay.find((item) => item.time.start == formattedTime);
if (findTime) {
const colSpan = calculateNumberOfCols(
findTime.time.start,
findTime.time.end,
timeInterval
);
i += colSpan - 1;
timeSlot.push({ ...findTime, colSpan });
} else timeSlot.push(undefined);
}
return timeSlot;
};
const startTime = startHour * 60;
if (startHour >= endHour) return timeSlot;

const colSlot = Math.ceil(((endHour - startHour) * 60) / timeInterval);
const used = new Set<number>();

for (let i = 0; i < colSlot; i++) {
const slotStart = startTime + i * timeInterval;
const slotEnd = slotStart + timeInterval;

const calculateNumberOfCols = (
startTime: string,
endTime: string,
intervalMinutes: number
): number => {
const startMinutes = convertToMinutes(startTime);
const endMinutes = convertToMinutes(endTime);
let foundIndex = -1;
for (let idx = 0; idx < findDay.length; idx++) {
if (used.has(idx)) continue;
const item = findDay[idx];
const s = convertToMinutes(item.time.start);
const e = convertToMinutes(item.time.end);

if (e > slotStart && s < slotEnd) {
foundIndex = idx;
break;
}
}

const numberOfCols = (endMinutes - startMinutes) / intervalMinutes;
if (foundIndex === -1) {
timeSlot.push(undefined);
continue;
}

return numberOfCols;
const item = findDay[foundIndex];
const s = convertToMinutes(item.time.start);
const e = convertToMinutes(item.time.end);

const effectiveStart = Math.max(s, slotStart);
const remainingMinutes = Math.max(0, e - effectiveStart);
let colSpan = Math.ceil(remainingMinutes / timeInterval);

colSpan = Math.min(colSpan, colSlot - i);

used.add(foundIndex);
timeSlot.push({ ...item, colSpan });
i += colSpan - 1;
}
return timeSlot;
};

const convertToMinutes = (time: string): number => {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/StudentTable.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
<div bind:this={captureScreen} class="p-1 dark:bg-gray-900 bg-white">
<Head {information} />
<div class="mb-auto mt-5">
<ScheduleTable {schedule} />
<ScheduleTable {schedule} startHourProp={8} endHourProp={21} />
</div>
</div>
<footer class="flex justify-between items-end">
Expand Down