Add single event page
This commit is contained in:
60
public/single.html
Normal file
60
public/single.html
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang='en'>
|
||||||
|
<head>
|
||||||
|
<meta charset='UTF-8'>
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||||
|
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
||||||
|
<link rel="manifest" href="/site.webmanifest">
|
||||||
|
|
||||||
|
<title>Event</title>
|
||||||
|
|
||||||
|
<link href='output.css' rel='stylesheet'>
|
||||||
|
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/qs/6.11.0/qs.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header class='fixed flex justify-between p-4 shadow-sm w-screen bg-white z-10'>
|
||||||
|
<a href='/'>
|
||||||
|
<h1 class='text-3xl'>Trip Schedule</h1>
|
||||||
|
</a>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div id='container' class='min-h-screen z-0 p-8 pt-20 bg-gray-100'>
|
||||||
|
<div id='event' class='shadow-xl rounded-md p-4 bg-white relative'>
|
||||||
|
<div class='flex gap-4 items-center'>
|
||||||
|
<h2 class='event-name text-3xl'></h2>
|
||||||
|
<span class='event-type py-0.5 px-3 rounded my-2 inline-block'></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='event-time-container my-4'>
|
||||||
|
<h3 class='text-2xl'>Times</h3>
|
||||||
|
<div class='event-start text-l'>
|
||||||
|
<span>Starts at: </span>
|
||||||
|
<span class='event-datetime'></span>
|
||||||
|
</div>
|
||||||
|
<div class='event-end text-l'>
|
||||||
|
<span>Ends at: </span>
|
||||||
|
<span class='event-datetime'></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='event-location-container my-4'>
|
||||||
|
<h3 class='text-2xl'>Location</h3>
|
||||||
|
<p class='event-location'>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='event-notes-container my-4'>
|
||||||
|
<h3 class='text-2xl'>Notes</h3>
|
||||||
|
<p class='event-notes'>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src='single.js' type='module'></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
65
public/single.js
Normal file
65
public/single.js
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
const $event = document.getElementById('event');
|
||||||
|
const searchParams = new URLSearchParams(document.location.search);
|
||||||
|
|
||||||
|
const eventId = searchParams.get('event');
|
||||||
|
|
||||||
|
const googleAPIEndpoint = 'https://www.google.com/maps/dir/?api=1';
|
||||||
|
|
||||||
|
const getDirectionLink = (location) => {
|
||||||
|
const $elem = document.createElement('a');
|
||||||
|
const encodedLocation = encodeURIComponent(location);
|
||||||
|
const dirLink = `${googleAPIEndpoint}&destination=${encodedLocation}`;
|
||||||
|
|
||||||
|
$elem.setAttribute('href', dirLink);
|
||||||
|
$elem.innerText = location;
|
||||||
|
|
||||||
|
$elem.classList.add('underline');
|
||||||
|
|
||||||
|
return $elem;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
if (!eventId)
|
||||||
|
return window.location.replace('/');
|
||||||
|
|
||||||
|
const query = {
|
||||||
|
sort: 'start',
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
equals: searchParams.get('event')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const stringifiedQuery = Qs.stringify({
|
||||||
|
...query
|
||||||
|
},
|
||||||
|
{
|
||||||
|
addQueryPrefix: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const res = await (await fetch(`/api/events${stringifiedQuery}`)).json();
|
||||||
|
const event = res.docs[0];
|
||||||
|
|
||||||
|
if (!event)
|
||||||
|
return window.location.replace('/');
|
||||||
|
|
||||||
|
document.title = `Event: ${event.name}`;
|
||||||
|
|
||||||
|
$event.querySelector('.event-name').innerText = event.name;
|
||||||
|
|
||||||
|
const typeElem = $event.querySelector('.event-type');
|
||||||
|
typeElem.innerText = event.type.value.name;
|
||||||
|
typeElem.style.backgroundColor = event.type.value.backgroundColour;
|
||||||
|
|
||||||
|
$event.querySelector('.event-start .event-datetime').innerText = event.start;
|
||||||
|
$event.querySelector('.event-end .event-datetime').innerText = event.end ? event.end : 'N/A';
|
||||||
|
|
||||||
|
if (event.location)
|
||||||
|
$event.querySelector('.event-location').appendChild(getDirectionLink(event.location));
|
||||||
|
|
||||||
|
$event.querySelector('.event-notes').innerText = event.notes ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
@@ -41,4 +41,6 @@ export interface Event {
|
|||||||
};
|
};
|
||||||
start: string;
|
start: string;
|
||||||
end?: string;
|
end?: string;
|
||||||
|
location?: string;
|
||||||
|
notes?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,4 +33,8 @@ payload.init({
|
|||||||
|
|
||||||
app.use(express.static(path.join(__dirname, '../public')));
|
app.use(express.static(path.join(__dirname, '../public')));
|
||||||
|
|
||||||
|
app.get(/^\/[0-9a-fA-F]{24}$/, (req, res) => {
|
||||||
|
res.redirect(`/single.html?event=${req.path.split('/')[1]}`);
|
||||||
|
});
|
||||||
|
|
||||||
app.listen(process.env.LISTEN_PORT);
|
app.listen(process.env.LISTEN_PORT);
|
||||||
|
|||||||
Reference in New Issue
Block a user