Skip to content

Commit e848120

Browse files
committed
feat(event): pagination page
1 parent f2fb368 commit e848120

File tree

2 files changed

+69
-45
lines changed

2 files changed

+69
-45
lines changed

client/my-app/src/components/features/events/EventCardGrid.tsx

Lines changed: 69 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@ export default function EventCardGrid({
2424
const [error, setError] = useState<string | null>(null);
2525
const [busyId, setBusyId] = useState<Event["event_id"] | null>(null);
2626

27+
const PAGE_SIZE = 4;
28+
const [page, setPage] = useState(1);
29+
2730
const doFetch: Fetcher =
2831
fetcher ?? (typeof fetch !== "undefined" ? fetch : (async () => new Response()) as any);
2932

3033
function handleUpdated(updated: Event) {
31-
// อัปเดต event ที่ถูกแก้ไขใน state ของ items
3234
setItems(prev => prev.map(it => it.event_id === updated.event_id ? updated : it));
3335
}
3436

@@ -53,24 +55,31 @@ export default function EventCardGrid({
5355
if (alive) setLoading(false);
5456
}
5557
})();
56-
return () => {
57-
alive = false;
58-
};
58+
return () => { alive = false; };
5959
}, [endpoint, doFetch]);
6060

61-
/** รวมค่าปัจจุบัน + ที่จะเปลี่ยน แล้วยิง PUT */
61+
/** --- Pagination --- */
62+
const total = items.length;
63+
const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE));
64+
const start = (page - 1) * PAGE_SIZE;
65+
const end = Math.min(start + PAGE_SIZE, total);
66+
const pageItems = items.slice(start, end);
67+
68+
useEffect(() => {
69+
if (page > totalPages) setPage(totalPages);
70+
}, [totalPages]);
71+
72+
/** --- PUT / Toggle functions --- */
6273
async function putMerged(id: number, patch: Partial<Pick<Event, "sensitivity" | "priority" | "status">>) {
63-
// หา current
6474
const cur = items.find(x => x.event_id === id);
6575
if (!cur) return;
6676

6777
const merged: Pick<Event, "sensitivity" | "priority" | "status"> = {
68-
sensitivity: (patch.sensitivity ?? cur.sensitivity) as any,
69-
priority: (patch.priority ?? cur.priority) as any,
70-
status: (patch.status ?? cur.status) as boolean,
78+
sensitivity: patch.sensitivity ?? cur.sensitivity,
79+
priority: patch.priority ?? cur.priority,
80+
status: patch.status ?? cur.status,
7181
};
7282

73-
// optimistic
7483
setItems(prev => prev.map(it => it.event_id === id ? { ...it, ...merged } : it));
7584

7685
try {
@@ -79,39 +88,24 @@ export default function EventCardGrid({
7988
method: "PUT",
8089
credentials: "include",
8190
cache: "no-store",
82-
headers: {
83-
"Content-Type": "application/json",
84-
Accept: "application/json",
85-
},
86-
body: JSON.stringify({
87-
sensitivity: merged.sensitivity,
88-
priority: merged.priority,
89-
status: merged.status,
90-
}),
91+
headers: { "Content-Type": "application/json", Accept: "application/json" },
92+
body: JSON.stringify(merged),
9193
});
9294
if (!res.ok) throw new Error(`HTTP ${res.status}`);
9395
} catch (err) {
94-
// rollback ง่ายๆด้วยการดึงของเดิมจาก cur
9596
setItems(prev => prev.map(it => it.event_id === id ? cur : it));
9697
console.error(err);
9798
} finally {
9899
setBusyId(null);
99100
}
100101
}
101102

102-
// Toggle → เรียก PUT พร้อมรวมค่าปัจจุบันของ sensitivity/priority
103103
async function toggleEnabled(id: Event["event_id"], next: boolean) {
104104
await putMerged(id, { status: next });
105105
}
106106

107-
// จาก dropdown → onEdit ส่ง item ทั้งตัวมา เราใช้เฉพาะ field ที่เกี่ยวแล้ว PUT
108107
async function updateItem(next: Event) {
109-
const patch: Partial<Pick<Event, "sensitivity" | "priority" | "status">> = {};
110-
// เราถือว่า next คือค่าที่ “ถูกแก้แล้ว” จากการ์ด
111-
patch.sensitivity = next.sensitivity;
112-
patch.priority = next.priority;
113-
patch.status = next.status;
114-
await putMerged(next.event_id, patch);
108+
await putMerged(next.event_id, { sensitivity: next.sensitivity, priority: next.priority, status: next.status });
115109
}
116110

117111
const gridCols = useMemo(
@@ -138,22 +132,53 @@ export default function EventCardGrid({
138132
}
139133

140134
return (
141-
<div className={`${gridCols} ${className ?? ""}`}>
142-
{items.map((it) => (
143-
<EventCard
144-
key={it.event_id}
145-
item={it}
146-
onToggle={toggleEnabled}
147-
onEdit={(v) => (onEdit ? onEdit(v) : updateItem(v))}
148-
onUpdated={handleUpdated}
149-
onDelete={(deletedItem: Event) => {
150-
setItems(prev => prev.filter(x => x.event_id !== deletedItem.event_id));
151-
onDelete?.(deletedItem);
152-
}}
153-
disabled={busyId === it.event_id}
154-
/>
155-
))}
156-
</div>
135+
<>
136+
<div className={`${gridCols} ${className ?? ""}`}>
137+
{pageItems.map(it => (
138+
<EventCard
139+
key={it.event_id}
140+
item={it}
141+
onToggle={toggleEnabled}
142+
onEdit={(v) => (onEdit ? onEdit(v) : updateItem(v))}
143+
onUpdated={handleUpdated}
144+
onDelete={(deletedItem: Event) => {
145+
setItems(prev => prev.filter(x => x.event_id !== deletedItem.event_id));
146+
onDelete?.(deletedItem);
147+
}}
148+
disabled={busyId === it.event_id}
149+
/>
150+
))}
151+
</div>
157152

153+
{/* --- Pagination bar --- */}
154+
<div className="mt-4 flex items-center justify-between">
155+
<div className="text-xs text-gray-500">
156+
Showing <span className="font-medium">{total ? start + 1 : 0}</span>
157+
<span className="font-medium">{end}</span> of <span className="font-medium">{total}</span>
158+
</div>
159+
160+
<div className="flex items-center gap-2">
161+
<button
162+
onClick={() => setPage(p => Math.max(1, p - 1))}
163+
disabled={page <= 1}
164+
className={`px-3 py-1 rounded-md border text-sm ${page <= 1 ? "text-gray-400 border-gray-200" : "text-gray-700 border-gray-300 hover:bg-gray-50"}`}
165+
>
166+
Previous
167+
</button>
168+
169+
<div className="text-sm tabular-nums">
170+
{page} / {totalPages}
171+
</div>
172+
173+
<button
174+
onClick={() => setPage(p => Math.min(totalPages, p + 1))}
175+
disabled={page >= totalPages}
176+
className={`px-3 py-1 rounded-md border text-sm ${page >= totalPages ? "text-gray-400 border-gray-200" : "text-gray-700 border-gray-300 hover:bg-gray-50"}`}
177+
>
178+
Next
179+
</button>
180+
</div>
181+
</div>
182+
</>
158183
);
159184
}

client/my-app/src/components/forms/events/EditEventForm.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ export default function EditEventForm({
7373
setSaveMsg("");
7474
setSaveStatus("info");
7575
}, [item]);
76-
console.log(item.icon_name);
7776

7877
async function updateEvent(payload: {
7978
icon_name: string;

0 commit comments

Comments
 (0)