initial commit
This commit is contained in:
13
src/app.d.ts
vendored
Normal file
13
src/app.d.ts
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import type { PrismaClient } from "@prisma/client"
|
||||
|
||||
declare global {
|
||||
namespace App {
|
||||
// interface Error {}
|
||||
// interface Locals {}
|
||||
// interface PageData {}
|
||||
// interface Platform {}
|
||||
}
|
||||
var __prisma: PrismaClient
|
||||
}
|
||||
|
||||
export {}
|
12
src/app.html
Normal file
12
src/app.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
<body data-sveltekit-preload-data="hover">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
7
src/index.test.ts
Normal file
7
src/index.test.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
describe('sum test', () => {
|
||||
it('adds 1 + 2 to equal 3', () => {
|
||||
expect(1 + 2).toBe(3);
|
||||
});
|
||||
});
|
9
src/lib/server/prisma.ts
Normal file
9
src/lib/server/prisma.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
|
||||
const prisma = global.__prisma || new PrismaClient()
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
global.__prisma = prisma
|
||||
}
|
||||
|
||||
export { prisma }
|
21
src/routes/+layout.svelte
Normal file
21
src/routes/+layout.svelte
Normal file
@@ -0,0 +1,21 @@
|
||||
<script lang="ts">
|
||||
import '@picocss/pico'
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<nav>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>
|
||||
<a href="/"> Blogly </a>
|
||||
</strong>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="/">Home</a></li>
|
||||
<li><a href="/register">Register</a></li>
|
||||
<li><a href="/login" role="button">Login</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<slot />
|
||||
</div>
|
57
src/routes/+page.server.ts
Normal file
57
src/routes/+page.server.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { Actions, PageServerLoad } from "./$types"
|
||||
import { prisma } from "$lib/server/prisma"
|
||||
import { fail } from "@sveltejs/kit"
|
||||
|
||||
export const load: PageServerLoad = async () => {
|
||||
return {
|
||||
articles: await prisma.article.findMany(),
|
||||
}
|
||||
}
|
||||
|
||||
export const actions: Actions = {
|
||||
createArticle: async ({ request }) => {
|
||||
const { title, content } = Object.fromEntries(await request.formData()) as {
|
||||
title: string
|
||||
content: string
|
||||
}
|
||||
|
||||
try {
|
||||
await prisma.article.create({
|
||||
data: {
|
||||
title,
|
||||
content,
|
||||
},
|
||||
})
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
return fail(500, { message: "Could not create the article." })
|
||||
}
|
||||
|
||||
return {
|
||||
status: 201,
|
||||
}
|
||||
},
|
||||
deleteArticle: async ({ url }) => {
|
||||
const id = url.searchParams.get("id")
|
||||
if (!id) {
|
||||
return fail(400, { message: "Invalid request" })
|
||||
}
|
||||
|
||||
try {
|
||||
await prisma.article.delete({
|
||||
where: {
|
||||
id: Number(id),
|
||||
},
|
||||
})
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
return fail(500, {
|
||||
message: "Something went wrong deleting your article",
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
}
|
||||
},
|
||||
}
|
35
src/routes/+page.svelte
Normal file
35
src/routes/+page.svelte
Normal file
@@ -0,0 +1,35 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types'
|
||||
|
||||
export let data: PageData
|
||||
|
||||
$: ({ articles } = data)
|
||||
</script>
|
||||
|
||||
<div class="grid">
|
||||
<div>
|
||||
<h2>Articles:</h2>
|
||||
{#each articles as article}
|
||||
<article>
|
||||
<header>{article.title}</header>
|
||||
<p>
|
||||
{article.content}
|
||||
</p>
|
||||
<form action="?/deleteArticle&id={article.id}" method="POST">
|
||||
<button type="submit" class="outline secondary">Delete Article</button>
|
||||
</form>
|
||||
<a href="/{article.id}" role="button" class="outline constrast" style="width: 100%;"
|
||||
>Edit Article</a
|
||||
>
|
||||
</article>
|
||||
{/each}
|
||||
</div>
|
||||
<form action="?/createArticle" method="POST">
|
||||
<h3>New Article</h3>
|
||||
<label for="title"> Title </label>
|
||||
<input type="text" id="title" name="title" />
|
||||
<label for="title"> Title </label>
|
||||
<textarea id="content" name="content" rows={5} />
|
||||
<button type="submit">Add Article</button>
|
||||
</form>
|
||||
</div>
|
49
src/routes/[articleId]/+page.server.ts
Normal file
49
src/routes/[articleId]/+page.server.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import type { Actions, PageServerLoad } from "./$types"
|
||||
import { prisma } from "$lib/server/prisma"
|
||||
import { error, fail } from "@sveltejs/kit"
|
||||
|
||||
export const load: PageServerLoad = async ({ params }) => {
|
||||
const getArticle = async () => {
|
||||
const article = await prisma.article.findUnique({
|
||||
where: {
|
||||
id: Number(params.articleId),
|
||||
},
|
||||
})
|
||||
if (!article) {
|
||||
throw error(404, "Article not found")
|
||||
}
|
||||
return article
|
||||
}
|
||||
|
||||
return {
|
||||
article: getArticle(),
|
||||
}
|
||||
}
|
||||
|
||||
export const actions: Actions = {
|
||||
updateArticle: async ({ request, params }) => {
|
||||
const { title, content } = Object.fromEntries(await request.formData()) as {
|
||||
title: string
|
||||
content: string
|
||||
}
|
||||
|
||||
try {
|
||||
await prisma.article.update({
|
||||
where: {
|
||||
id: Number(params.articleId),
|
||||
},
|
||||
data: {
|
||||
title,
|
||||
content,
|
||||
},
|
||||
})
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
return fail(500, { message: "Could not update article" })
|
||||
}
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
}
|
||||
},
|
||||
}
|
15
src/routes/[articleId]/+page.svelte
Normal file
15
src/routes/[articleId]/+page.svelte
Normal file
@@ -0,0 +1,15 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types'
|
||||
|
||||
export let data: PageData
|
||||
$: ({ article } = data)
|
||||
</script>
|
||||
|
||||
<form action="?/updateArticle" method="POST">
|
||||
<h3>Editing: {article.title}</h3>
|
||||
<label for="title"> Title </label>
|
||||
<input type="text" id="title" name="title" value={article.title} />
|
||||
<label for="title"> Title </label>
|
||||
<textarea id="content" name="content" rows={5} value={article.content} />
|
||||
<button type="submit">Update Article</button>
|
||||
</form>
|
0
src/routes/login/+page.server.ts
Normal file
0
src/routes/login/+page.server.ts
Normal file
14
src/routes/login/+page.svelte
Normal file
14
src/routes/login/+page.svelte
Normal file
@@ -0,0 +1,14 @@
|
||||
<form>
|
||||
<hgroup>
|
||||
<h2>Login</h2>
|
||||
<h3>Welcome back!</h3>
|
||||
</hgroup>
|
||||
<label for="email">Email address</label>
|
||||
<input type="email" id="email" name="email" required />
|
||||
|
||||
<label for="email">Password</label>
|
||||
<input type="email" id="email" name="password" required />
|
||||
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
||||
<p>Don't have an account? <a href="/register">Register</a></p>
|
0
src/routes/register/+page.server.ts
Normal file
0
src/routes/register/+page.server.ts
Normal file
26
src/routes/register/+page.svelte
Normal file
26
src/routes/register/+page.svelte
Normal file
@@ -0,0 +1,26 @@
|
||||
<form>
|
||||
<hgroup>
|
||||
<h2>Register</h2>
|
||||
<h3>To post articles, you'll need an account.</h3>
|
||||
</hgroup>
|
||||
<div class="grid">
|
||||
<label for="firstname">
|
||||
First name
|
||||
<input type="text" id="firstname" name="firstname" required />
|
||||
</label>
|
||||
|
||||
<label for="lastname">
|
||||
Last name
|
||||
<input type="text" id="lastname" name="lastname" required />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label for="email">Email address</label>
|
||||
<input type="email" id="email" name="email" required />
|
||||
|
||||
<label for="email">Password</label>
|
||||
<input type="email" id="email" name="password" required />
|
||||
|
||||
<button type="submit">Register</button>
|
||||
</form>
|
||||
<p>Already have an account? <a href="/login">Login</a></p>
|
Reference in New Issue
Block a user