180 lines
5.0 KiB
TypeScript
180 lines
5.0 KiB
TypeScript
import React, { useState, useEffect } from "react";
|
|
import { NextPage } from "next";
|
|
import useSWR from "swr";
|
|
import { formatRelative } from "date-fns";
|
|
import { toast } from "react-toastify";
|
|
import styled from "styled-components";
|
|
import AdminListCommon from "@views/admin/AdminListCommon";
|
|
import { Button, Link } from "@components/index";
|
|
import AddLink from "@components/AddLink";
|
|
import Event from "@models/Event";
|
|
import EventApi from "@api/eventApi";
|
|
import { fetcher, APIPath, API } from "@api/backend";
|
|
|
|
const URL = "/admin/events";
|
|
|
|
const StyledButton = styled(Button) <{ $colorOverride: "red" }>`
|
|
background-color: ${(p) => p.$colorOverride};
|
|
border-radius: 8px;
|
|
color: white;
|
|
font-size: 13px;
|
|
font-weight: bold;
|
|
`;
|
|
|
|
const StyledSelect = styled.select`
|
|
padding: 0.25rem;
|
|
`;
|
|
|
|
const SelectWrapper = styled.div`
|
|
padding: 0.25rem;
|
|
`;
|
|
|
|
const confirmDelete = async (event: Event) => {
|
|
if (window.confirm(`Delete: ${event.id}: ${event.title_fi}/${event.title_en}; Are you sure?`) === true) {
|
|
try {
|
|
await EventApi.deleteEvent(event.id);
|
|
toast.success("Event removed successfully 😎");
|
|
window.location.reload(); // TODO: Fetch/update event list, so user sees the signup in the list
|
|
} catch (err) {
|
|
toast.error("Uh oh! Something went wrong! Try again later. 😟");
|
|
}
|
|
}
|
|
};
|
|
|
|
const Renderer: React.FC = () => {
|
|
const api: API = { path: APIPath.EVENTS, authenticated: true };
|
|
const { data: events, error } = useSWR<Event[]>(api, fetcher);
|
|
|
|
const [sort, setSort] = useState<string>("start_time");
|
|
const [order, setOrder] = useState<string>("descending");
|
|
const [filter, setFilter] = useState<string>("all");
|
|
|
|
const [processedEvents, setProcessedEvents] = useState<Event[]>([]);
|
|
|
|
useEffect(() => {
|
|
console.log("hook call");
|
|
|
|
const eventSort = (a, b) => {
|
|
let result = 0;
|
|
|
|
console.log(order);
|
|
console.log(sort);
|
|
|
|
if (order === "ascending") {
|
|
if (sort in ["start_time", "end_time"]) {
|
|
result = new Date(b[sort]).getTime() - new Date(a[sort]).getTime();
|
|
} else if (sort === "id") {
|
|
result = b[sort] - a[sort];
|
|
}
|
|
} else if (order === "descending") {
|
|
if (sort in ["start_time", "end_time"]) {
|
|
result = new Date(a[sort]).getTime() - new Date(b[sort]).getTime();
|
|
} else if (sort === "id") {
|
|
result = a[sort] - b[sort];
|
|
}
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
const checkDate = (a) => {
|
|
let result = true;
|
|
|
|
if (filter === "upcoming") {
|
|
result = new Date(a.end_time).getTime() > Date.now();
|
|
} else if (filter === "past") {
|
|
result = new Date(a.end_time).getTime() < Date.now();
|
|
console.log(`Past ${result}`);
|
|
}
|
|
return result;
|
|
};
|
|
|
|
if (events) {
|
|
setProcessedEvents(events.sort(eventSort).filter(checkDate));
|
|
}
|
|
}, [sort, order, filter, events]);
|
|
|
|
function handleSortChange(e) {
|
|
setSort(e.target.value);
|
|
}
|
|
|
|
function handleOrderChange(e) {
|
|
setOrder(e.target.value);
|
|
}
|
|
|
|
function handleFilterChange(e) {
|
|
setFilter(e.target.value);
|
|
}
|
|
|
|
if (error) {
|
|
console.error(error);
|
|
return (
|
|
<div>
|
|
Failed loading events.
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!events?.length) {
|
|
return <div>No events.</div>;
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<div>
|
|
Sort by:
|
|
<select name="" onChange={handleSortChange}>
|
|
<option value="start_time">Start time</option>
|
|
<option value="end_time">End time</option>
|
|
<option value="id">Creation order</option>
|
|
</select>
|
|
Order:
|
|
<select name="" onChange={handleOrderChange}>
|
|
<option value="descending">Descending</option>
|
|
<option value="ascending">Ascending</option>
|
|
</select>
|
|
Filter:
|
|
<select name="" onChange={handleFilterChange}>
|
|
<option value="upcoming">Upcoming</option>
|
|
<option value="all">All</option>
|
|
<option value="past">Past</option>
|
|
</select>
|
|
</div>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Title</th>
|
|
<th>Start time</th>
|
|
<th>End time</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{processedEvents
|
|
.map((event) => (
|
|
<tr key={event.id}>
|
|
<td><Link to={`${URL}/${event.id}`}>{event.title_fi}</Link></td>
|
|
<td>{formatRelative(new Date(event.start_time), new Date())}</td>
|
|
<td>{formatRelative(new Date(event.end_time), new Date())}</td>
|
|
<td>
|
|
<StyledButton $colorOverride="red" buttonStyle="filled" onClick={() => confirmDelete(event)}>
|
|
Delete
|
|
</StyledButton>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const AdminEventPage: NextPage = () => (
|
|
<AdminListCommon>
|
|
<h1>Events</h1>
|
|
<AddLink text="Create event" to={`${URL}/create`} data-e2e="create-event" />
|
|
<Renderer />
|
|
</AdminListCommon>
|
|
);
|
|
|
|
export default AdminEventPage;
|