Refactor database schema and add planner functionality
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
export let regionId: String | undefined = undefined;
|
||||
export let visited: Boolean | undefined = undefined;
|
||||
export let countryCode: String | undefined = undefined;
|
||||
export let activityTypes: String[] | undefined = undefined;
|
||||
|
||||
function remove() {
|
||||
dispatch("remove", id);
|
||||
@@ -126,3 +127,25 @@
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if type === "planner"}
|
||||
<div
|
||||
class="card min-w-max lg:w-96 md:w-80 sm:w-60 xs:w-40 bg-primary-content shadow-xl overflow-hidden text-base-content"
|
||||
>
|
||||
<div class="card-body">
|
||||
<h2 class="card-title overflow-ellipsis">{name}</h2>
|
||||
{#if location != ""}
|
||||
<div class="inline-flex items-center">
|
||||
<iconify-icon icon="mdi:map-marker" class="text-xl"></iconify-icon>
|
||||
<p class="ml-.5">{location}</p>
|
||||
</div>
|
||||
{/if}
|
||||
{#if activityTypes && activityTypes.length > 0}
|
||||
<p>{activityTypes}</p>
|
||||
{/if}
|
||||
<div class="card-actions justify-end">
|
||||
<button class="btn btn-primary" on:click={add}>Add</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -78,6 +78,10 @@
|
||||
<button class="btn btn-primary my-2 md:my-0 md:mr-4" on:click={goToLog}
|
||||
>My Log</button
|
||||
>
|
||||
<button
|
||||
class="btn btn-primary my-2 md:my-0 md:mr-4"
|
||||
on:click={() => goto("/planner")}>Planner</button
|
||||
>
|
||||
{/if}
|
||||
<button
|
||||
class="btn btn-primary my-2 md:my-0 md:mr-4"
|
||||
|
||||
@@ -89,4 +89,14 @@ export const userVisitedWorldTravel = pgTable("userVisitedWorldTravel", {
|
||||
region_id: varchar("region_id")
|
||||
.notNull()
|
||||
.references(() => worldTravelCountryRegions.id),
|
||||
});
|
||||
});
|
||||
|
||||
export const userPlannedAdventures = pgTable("userPlannedAdventures", {
|
||||
id: serial("id").primaryKey(),
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.references(() => userTable.id),
|
||||
name: text("adventureName").notNull(),
|
||||
location: text("location"),
|
||||
activityTypes: json("activityTypes"),
|
||||
});
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
export interface Adventure {
|
||||
id: number;
|
||||
name: string;
|
||||
location: string;
|
||||
created: string;
|
||||
id?: number;
|
||||
name?: string;
|
||||
location?: string | undefined;
|
||||
created?: string | undefined;
|
||||
description?: string | undefined;
|
||||
activityTypes?: string[] | undefined;
|
||||
}
|
||||
|
||||
export interface RegionInfo {
|
||||
@@ -36,4 +38,4 @@ export interface RegionInfo {
|
||||
attractions: string[];
|
||||
};
|
||||
major_sports_teams: string[];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -135,10 +135,10 @@
|
||||
(adventure) => adventure.id === event.detail
|
||||
);
|
||||
if (adventure) {
|
||||
editId = adventure.id;
|
||||
editName = adventure.name;
|
||||
editLocation = adventure.location;
|
||||
editCreated = adventure.created;
|
||||
editId = adventure.id || 0;
|
||||
editName = adventure.name || "";
|
||||
editLocation = adventure.location || "";
|
||||
editCreated = adventure.created || "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
21
src/routes/planner/+page.server.ts
Normal file
21
src/routes/planner/+page.server.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { db } from "$lib/db/db.server";
|
||||
import { userPlannedAdventures } from "$lib/db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import type { LayoutServerLoad } from "../$types";
|
||||
import { redirect } from "@sveltejs/kit";
|
||||
|
||||
export const load: LayoutServerLoad = async (event) => {
|
||||
if (event.locals.user) {
|
||||
let plannedAdventures = await db
|
||||
.select()
|
||||
.from(userPlannedAdventures)
|
||||
.where(eq(userPlannedAdventures.userId, event.locals.user.id));
|
||||
return {
|
||||
user: event.locals.user,
|
||||
isServerSetup: event.locals.isServerSetup,
|
||||
plannedAdventures,
|
||||
};
|
||||
} else {
|
||||
return redirect(302, "/login");
|
||||
}
|
||||
};
|
||||
29
src/routes/planner/+page.svelte
Normal file
29
src/routes/planner/+page.svelte
Normal file
@@ -0,0 +1,29 @@
|
||||
<script lang="ts">
|
||||
import { page } from "$app/stores";
|
||||
import type { Adventure } from "$lib/utils/types";
|
||||
import { onMount } from "svelte";
|
||||
import AdventureCard from "$lib/components/AdventureCard.svelte";
|
||||
|
||||
let plannedAdventures: Adventure[] = [];
|
||||
|
||||
onMount(async () => {
|
||||
plannedAdventures = $page.data.plannedAdventures;
|
||||
console.log(plannedAdventures);
|
||||
});
|
||||
</script>
|
||||
|
||||
<h1 class="font-extrabold text-center text-4xl">My Planned Adventures</h1>
|
||||
|
||||
<div
|
||||
class="grid xl:grid-cols-3 lg:grid-cols-3 md:grid-cols-2 sm:grid-cols-1 gap-4 mt-4 content-center auto-cols-auto ml-6 mr-6"
|
||||
>
|
||||
{#each plannedAdventures as adventure (adventure.id)}
|
||||
<AdventureCard
|
||||
type="planner"
|
||||
id={adventure.id}
|
||||
name={adventure.name}
|
||||
location={adventure.location}
|
||||
activityTypes={adventure.activityTypes}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
@@ -1,11 +1,20 @@
|
||||
import { error, redirect, type Actions, type Handle } from "@sveltejs/kit";
|
||||
import type { PageServerLoad } from "./$types";
|
||||
import { db } from "$lib/db/db.server";
|
||||
import { sessionTable, userTable } from "$lib/db/schema";
|
||||
import {
|
||||
sessionTable,
|
||||
userTable,
|
||||
userVisitedAdventures,
|
||||
userVisitedWorldTravel,
|
||||
} from "$lib/db/schema";
|
||||
import type { DatabaseUser } from "$lib/server/auth";
|
||||
import { count } from "drizzle-orm";
|
||||
|
||||
export const load: PageServerLoad = async (event) => {
|
||||
let users: DatabaseUser[] = [];
|
||||
let visitCount: number = NaN;
|
||||
let userCount: number = NaN;
|
||||
let regionCount: number = NaN;
|
||||
if (!event.locals.user) {
|
||||
return redirect(302, "/login");
|
||||
}
|
||||
@@ -14,9 +23,24 @@ export const load: PageServerLoad = async (event) => {
|
||||
}
|
||||
if (event.locals.user.role === "admin") {
|
||||
users = (await db.select().from(userTable).execute()) as DatabaseUser[];
|
||||
visitCount = (await db
|
||||
.select({ count: count() })
|
||||
.from(userVisitedAdventures)
|
||||
.execute()) as unknown as number;
|
||||
userCount = (await db
|
||||
.select({ count: count() })
|
||||
.from(userTable)
|
||||
.execute()) as unknown as number;
|
||||
regionCount = (await db
|
||||
.select({ count: count() })
|
||||
.from(userVisitedWorldTravel)
|
||||
.execute()) as unknown as number;
|
||||
}
|
||||
return {
|
||||
users,
|
||||
visitCount,
|
||||
userCount,
|
||||
regionCount,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -58,12 +58,16 @@
|
||||
console.log(errors);
|
||||
cancel();
|
||||
};
|
||||
|
||||
let visitCount = $page.data.visitCount[0].count;
|
||||
let userCount = $page.data.userCount[0].count;
|
||||
let regionCount = $page.data.regionCount[0].count;
|
||||
</script>
|
||||
|
||||
<h1 class="text-center font-extrabold text-4xl">Admin Settings</h1>
|
||||
|
||||
<h2 class="text-center font-extrabold text-2xl">Add User</h2>
|
||||
<div class="flex justify-center">
|
||||
<div class="flex justify-center mb-4">
|
||||
<form
|
||||
method="POST"
|
||||
action="/signup"
|
||||
@@ -125,7 +129,7 @@
|
||||
|
||||
<h2 class="text-center font-extrabold text-2xl">User Managment</h2>
|
||||
<div
|
||||
class="grid xl:grid-cols-3 lg:grid-cols-3 md:grid-cols-2 sm:grid-cols-1 gap-4 mt-4 content-center auto-cols-auto ml-6 mr-6"
|
||||
class="grid xl:grid-cols-3 lg:grid-cols-3 md:grid-cols-2 sm:grid-cols-1 gap-4 mt-4 content-center auto-cols-auto ml-6 mr-6 mb-4"
|
||||
>
|
||||
{#each $page.data.users as user}
|
||||
<div>
|
||||
@@ -143,3 +147,31 @@
|
||||
message="Are you sure you want to clear all user sessions?"
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<h2 class="text-center font-extrabold text-2xl">Admin Stats (All Users)</h2>
|
||||
<div class="flex items-center justify-center mb-4">
|
||||
<div class="stats stats-vertical lg:stats-horizontal shadow">
|
||||
<div class="stat">
|
||||
<div class="stat-title">Total Visits</div>
|
||||
<div class="stat-value">{visitCount}</div>
|
||||
</div>
|
||||
|
||||
<div class="stat">
|
||||
<div class="stat-title">Total Users</div>
|
||||
<div class="stat-value">{userCount}</div>
|
||||
</div>
|
||||
|
||||
<div class="stat">
|
||||
<div class="stat-title">Visited Regions</div>
|
||||
<div class="stat-value">{regionCount}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<svelte:head>
|
||||
<title>Admin Settings | AdventureLog</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Admin Settings for AdventureLog. Add users, manage sessions, and more!"
|
||||
/>
|
||||
</svelte:head>
|
||||
|
||||
@@ -32,4 +32,4 @@
|
||||
name="description"
|
||||
content="Explore the world and add countries to your visited list!"
|
||||
/>
|
||||
</svelte:head>;
|
||||
</svelte:head>
|
||||
|
||||
Reference in New Issue
Block a user