Skip to content

Commit

Permalink
Lots of work done (Read More)
Browse files Browse the repository at this point in the history
- Database.TS moved to lib/server for security
- Added a footer
- Used +layout to ensure cookies are set
- Finished /admin/events, and /admin/events/create
- Fixed broken Favicon
  • Loading branch information
RJMurg committed Sep 5, 2023
1 parent aba1824 commit 0f60f91
Show file tree
Hide file tree
Showing 16 changed files with 301 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,4 @@ npm run dev
8. You're done! You can now create your own treasure hunt.

## Documentation
The documentation for BitHunt can be found in the [docs]('/docs') directory.
The documentation for BitHunt can be found in the [docs]('docs') directory.
7 changes: 5 additions & 2 deletions docs/routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,17 @@ Once complete, each route will be marked with a checkbox.
## Admin Routes

- [X] `/admin` - The main admin page, this is where admins log in to the Admin portal.
- [ ] `/admin/events` - The events page, this is where admins can view, create, edit and delete events.
- [ ] `/admin/events/create` - The create event page, this is where admins can create a new event.
- [X] `/admin/events` - The events page, this is where admins can view, create, edit and delete events.
- [X] `/admin/events/create` - The create event page, this is where admins can create a new event.
- [ ] `/admin/events/remove/:id` - The remove event page, this is where admins can remove an existing event.
- [ ] `/admin/events/:id` - The edit event page, this is where admins can edit an existing event.
- [ ] `/admin/stages` - The stages page, this is where admins can view, create, edit and delete stages.
- [ ] `/admin/stages/create` - The create stage page, this is where admins can create a new stage.
- [ ] `/admin/stages/remove/:id` - The remove stage page, this is where admins can remove an existing stage.
- [ ] `/admin/stages/:id` - The edit stage page, this is where admins can edit an existing stage.
- [ ] `/admin/puzzles` - The puzzles page, this is where admins can view, create, edit and delete puzzles.
- [ ] `/admin/puzzles/create` - The create puzzle page, this is where admins can create a new puzzle.
- [ ] `/admin/puzzles/remove/:id` - The remove puzzle page, this is where admins can remove an existing puzzle.
- [ ] `/admin/puzzles/:id` - The edit puzzle page, this is where admins can edit an existing puzzle.
- [ ] `/admin/leaderboard` - The leaderboard page, this is where admins can view and edit the leaderboard.
- [ ] `/admin/overall` - The overall page, this is where admins can view and edit the overall game stats.
2 changes: 1 addition & 1 deletion src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/BitBox-Thumb.png" />
<link rel="icon" href="%sveltekit.assets%/bitbox-thumb.png" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="http://fonts.googleapis.com/css?family=IBM+Plex+Sans">
Expand Down
Empty file added src/lib/assets/footer.svelte
Empty file.
3 changes: 3 additions & 0 deletions src/lib/database.ts → src/lib/server/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,5 +138,8 @@ export const databaseIntegrity = async (databaseURL: any) => {
}
}

// Close connection
await client.end();

return returnVal;
};
9 changes: 9 additions & 0 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script lang="ts">
import Cspp from "$lib/assets/cspp-thumb.png";
</script>

<slot></slot>

<footer>
Created with ❤️ (and Svelte) by <img class="footerimg" src={Cspp} alt="The CS++ Logo">
</footer>
18 changes: 18 additions & 0 deletions src/routes/admin/+layout.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { redirect } from '@sveltejs/kit';
import type { LayoutServerLoad } from './$types';

export const load: LayoutServerLoad = async ({ request, cookies }) => {
let rawURL = request.url;
let url = new URL(rawURL);
let path = url.pathname;

// Check if admin cookie is set
if (cookies.get('admin') !== 'true' && path !== "/admin") {
throw redirect(301, "/admin")
}
else{
return{
loggedIn: true
}
}
}
1 change: 1 addition & 0 deletions src/routes/admin/+layout.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<slot></slot>
2 changes: 1 addition & 1 deletion src/routes/admin/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { redirect } from '@sveltejs/kit';
import { databaseIntegrity } from '$lib/database';
import { databaseIntegrity } from '$lib/server/database';
import type { PageServerLoad, Actions } from './$types';

// Read in info from .env file
Expand Down
2 changes: 1 addition & 1 deletion src/routes/admin/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
</script>

<head>
<title>BitHunt - Admin Portal</title>
<title>BitHunt [🛡️] - Admin Portal</title>
</head>

<Toasts />
Expand Down
24 changes: 24 additions & 0 deletions src/routes/admin/events/+page.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { PageServerLoad } from './$types';
import pg from 'pg';
const { Pool } = pg;

// Read in info from .env file
import { config } from 'dotenv';
config();

const pool = new Pool({
connectionString: process.env.DATABASE_URL
});

export const load = (async () => {
// Get a list of all events
const events = await pool.query(`
SELECT *
FROM events
`);

return {
status: 200,
events: events.rows
};
}) satisfies PageServerLoad;
83 changes: 83 additions & 0 deletions src/routes/admin/events/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<script lang="ts">
import type { PageData } from './$types';
export let data: PageData;
export let eventView = (id: string) => {
window.location.href = "/admin/events/" + id;
},
eventRemove = (id: string) => {
let confirmation = confirm("Are you sure you want to delete this event?");
if(confirmation){
window.location.href = "/admin/events/remove/" + id;
}
}
</script>

<head>
<title>BitHunt [🛡️] - Events</title>
</head>

<h1 class="title large">Events</h1>

<div class="buttons">
<button class="cspp" on:click={() => window.location.href = "/admin"}>
<i class="fa fa-arrow-left"></i>
Go Back
</button>
<button class="cspp" on:click={() => window.location.href = "/admin/events/create"}>
<i class="fa fa-calendar-plus-o"></i>
Add New
</button>
</div>

<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Date</th>
<th>Location</th>
<th>Description</th>
<th>Prize</th>
<th>Prize Count</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{#each data.events as event}
<tr>
<td>{event.name}</td>
<td>{event.date}</td>
<td>{event.location}</td>
<td>{event.description}</td>
<td>{event.prize}</td>
<td>{event.prizecount}</td>
<td>{event.status}</td>
<td>
<div class="actions">
<button class="action " on:click={() => eventView(event.id)}>
<i class="fa fa-eye"></i>
</button>
<button class="action" on:click={() => eventRemove(event.id)}>
<i class="fa fa-trash"></i>
</button>
</div>
</td>
</tr>
{/each}

{#if data.events.length == 0}
<tr>
<td colspan="8">No events found.</td>
</tr>
{/if}
</tbody>
</table>
42 changes: 42 additions & 0 deletions src/routes/admin/events/create/+page.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { redirect } from '@sveltejs/kit';
import type { Actions } from './$types';
import pg from 'pg';
const { Pool } = pg;

// Read in info from .env file
import { config } from 'dotenv';
config();

const pool = new Pool({
connectionString: process.env.DATABASE_URL
});

export const actions = {
default: async ({cookies, request}) => {
let reqData = await request.formData();
// Returns as format:
// FormData {
// 'name' => "string",
// 'date' => "string",
// 'location' => "string",
// 'description' => "string",
// 'prize' => "string",
// 'prizeCount' => "number",
// 'status' => "string",

// Change Status to boolean
let status = reqData.get('status') === "true" ? true : false;

// Add to database
await pool.query(
'INSERT INTO events (name, date, location, description, prize, prizeCount, active) VALUES ($1, $2, $3, $4, $5, $6, $7)',
[reqData.get('name'), reqData.get('date'), reqData.get('location'), reqData.get('description'), reqData.get('prize'), reqData.get('prizeCount'), status]
);

return{
status: 200,
message: reqData.get('name') + " created successfully"
}

}
} satisfies Actions;
86 changes: 86 additions & 0 deletions src/routes/admin/events/create/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<script lang="ts">
import type { ActionData } from './$types';
import Toasts from "$lib/toasts/Toasts.svelte";
import { addToast } from "$lib/toasts/store.js";
export let form: ActionData;
let date = new Date().toISOString().slice(0, 10);
// Create toast
if(form?.status == 200){
addToast({
type: "success",
message: form?.message,
dismissible: true,
timeout: 5000
})
}
</script>

<head>
<title>BitHunt [🛡️] - Create Event</title>
</head>

<Toasts />

<h1 class="title large">Create an Event</h1>

<button class="cspp form-element" on:click={() => window.location.href = "/admin/events"}>
<i class="fa fa-arrow-left"></i>
Back
</button>

<form method="post">
<label for="name">
Name
<span class="required">*</span>
</label>
<input type="text" name="name" id="name" placeholder="Event Name" required>

<label for="date">
Date
<span class="required">*</span>
</label>
<input type="date" name="date" id="date" bind:value={date} required>

<label for="location">
Location
<span class="required">*</span>
</label>
<input type="text" name="location" id="location" placeholder="Event Location" required>

<label for="description">
Description
<span class="required">*</span>
</label>
<textarea name="description" id="description" placeholder="Event Description" required></textarea>

<label for="prize">
Prize
<span class="required">*</span>
</label>
<input type="text" name="prize" id="prize" placeholder="Event Prize" required>

<label for="prizeCount">
Prize Count
<span class="required">*</span>
</label>
<input type="number" name="prizeCount" id="prizeCount" placeholder="Event Prize Count" required>

<label for="status">
Status
<span class="required">*</span>
</label>
<select name="status" id="status" required>
<option value="false">Inactive</option>
<option value="true">Active</option>
</select>

<button type="submit" class="cspp form-element primary">
<i class="fa fa-calendar-plus-o"></i>
Create Event
</button>

</form>
Binary file added static/bitbox-thumb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,10 @@ td{
}

.action{
font-size: 1.5rem;
vertical-align: middle;
display: inline;
background: none;
box-shadow: none;
transform: scale(1);
transition: 0.5 ease-in-out;
Expand Down Expand Up @@ -474,4 +478,26 @@ input[disabled]{
border: none;
background-color: transparent;
color: var(--white);
}

/* put at very bottom of page */
footer{
position: fixed;
bottom: 0;
width: 100%;
height: 2.5rem;
font-family: 'IBM Plex Sans', sans-serif;
font-weight: 200;
text-align: center;
padding: 0.5rem;
text-shadow: inset 0 0 5px 5px var(--black);
}

.footerimg{
width: 1.75rem;
height: auto;
margin: 0;
padding: 0;
vertical-align: middle;
display: inline;
}

0 comments on commit 0f60f91

Please sign in to comment.