Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update endpoints with sqlite and integrate with frontend #32

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 56 additions & 28 deletions packages/backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Elysia, t } from 'elysia'
import { migrate } from 'drizzle-orm/bun-sqlite/migrator'
import { db } from './db/db'
import { todos } from './db/schema'
import { eq } from 'drizzle-orm'

migrate(db, { migrationsFolder: './drizzle' })

Expand Down Expand Up @@ -38,14 +39,15 @@ const app = new Elysia()
.get('/todos', () => db.select().from(todos))
.get(
'/todos/:id',
({ params, error }) => {
const todo = todoList.find((todo) => todo.id === params.id)
async ({params, set, body, error}) => {
const todo = await db.select().from(todos).where(eq(todos.id, params.id))

if (!todo) {
return error(404, 'Todo not found.')
if(!todo[0]) {
return error(404, 'Todo not found');
}

return todo
set.status = 'OK'
return todo[0]
},
{
params: t.Object({
Expand All @@ -56,27 +58,41 @@ const app = new Elysia()
.post(
'/todos',
async ({ body, set }) => {
await db.insert(todos).values(body)
let newTodo = await db.insert(todos)
.values(body)
.returning()
console.log(newTodo)
set.status = 'Created'
return {
"id": newTodo[0].id
};
},
{
body: t.Object({
desc: t.String()
desc: t.String(),
starred: t.Boolean(),
completed: t.Boolean()
})
}
)
.put(
'/todos/:id',
({ params, body, error }) => {
const todo = todoList.find((todo) => todo.id === params.id)
async ({params, set, body, error}) => {
const todo = await db.select().from(todos).where(eq(todos.id, params.id))

if (!todo) {
return error(204, 'Todo can not be updated.')
if(!todo[0]) {
return error(404, 'Todo not found for update');
}

Object.assign(todo, body)
const updatedTodo = await db.update(todos)
.set(body)
.where(eq(todos.id, params.id))
.returning()
if(!updatedTodo[0]) {
return error(500, 'Todo could not be updated')
}

return todo
set.status = 'OK'
},
{
params: t.Object({
Expand All @@ -91,16 +107,22 @@ const app = new Elysia()
)
.patch(
'/todos/:id',
({ params, body, error }) => {
const todo = todoList.find((todo) => todo.id === params.id)
async ({params, set, body, error}) => {
const todo = await db.select().from(todos).where(eq(todos.id, params.id))

if (!todo) {
return error(204, 'Todo can not be updated.')
if(!todo[0]) {
return error(404, 'Todo not found for update');
}

Object.assign(todo, body)
const updatedTodo = await db.update(todos)
.set(body)
.where(eq(todos.id, params.id))
.returning()
if(!updatedTodo[0]) {
return error(500, 'Todo could not be updated')
}

return todo
set.status = 'OK'
},
{
params: t.Object({
Expand All @@ -115,16 +137,22 @@ const app = new Elysia()
)
.delete(
'/todos/:id',
({ params, error }) => {
const todo = todoList.find((todo) => todo.id === params.id)

if (!todo) {
return error(204, 'Todo can not be deleted.')
async ({ params, set, error }) => {
try {
const deletedTodo = await db.delete(todos)
.where(eq(todos.id, params.id))
.returning();

if (!deletedTodo) {
return error(404, 'Todo not found for deletion.');
}

set.status = 'No Content'
return
} catch (err) {
console.error('Error deleting todo:', err);
return error(500, "Interval server error: " + err);
}

todoList.splice(todoList.indexOf(todo), 1)

return todo
},
{
params: t.Object({
Expand Down
144 changes: 133 additions & 11 deletions packages/frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useEffect, useRef, useState } from 'react'
import { Input } from './components/ui/input'
import type { App } from 'backend/src/index'
import { treaty } from '@elysiajs/eden'
import { compileFunction } from 'vm'

const client = treaty<App>('localhost:3000')

Expand Down Expand Up @@ -79,34 +80,155 @@ function App() {
})
}, [])

const handleDelete = (id: number) =>
setTodos(todos.filter((todo) => todo.id !== id))
const handleDelete = (id: number) => {
let toDelete = todos.filter((todo) => todo.id === id)[0]
setTodos(prev => prev.filter((todo) => todo.id !== id))

client.todos({id})
.delete()
.then((res) => {
if(res.error) {
setTodos(prev => [...prev, toDelete])
}

if(res.data) {
// do nothing?
}
})
.catch((error) => {
// Handle errors, including timeouts
console.error('Error sending request:', error);
// Revert optimistic update
setTodos(prev => [...prev, toDelete]);
})
}



const toggleStar = (id: number) =>{
let toggleTodo = todos.find((todo) => todo.id === id)
if(!toggleTodo) {
return
}

let initialState = toggleTodo?.starred

const toggleStar = (id: number) =>
setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, starred: !todo.starred } : todo
)
)

const toggleChecked = (id: number) =>
client.todos({id})
.patch({
starred: !initialState
})
.then((res) => {
if(res.error) {
setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, starred: !todo.starred } : todo
)
)
}
})
.catch((error) => {
// Handle errors, including timeouts
console.error('Error sending request:', error);
// Revert optimistic update (remove temporary todo)
setTodos(todos.map((todo) =>
todo.id === id ? { ...todo, starred: !todo.starred } : todo
));
})
}

const toggleChecked = (id: number) =>{
let toggleTodo = todos.find((todo) => todo.id === id)
if(!toggleTodo) {
return
}

let initialState = toggleTodo?.completed

setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
)

client.todos({id})
.patch({
completed: !initialState
})
.then((res) => {
if(res.error) {
setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
)
}
})
.catch((error) => {
// Handle errors, including timeouts
console.error('Error sending request:', error);
// Revert optimistic update (remove temporary todo)
setTodos(todos.map((todo) =>
todo.id === id ? { ...todo, starred: !todo.starred } : todo
));
})
}

const addTodo = () => {
setTodos([
...todos,

let toAdd = {
desc: inputRef.current!.value,
starred: false,
completed: false,
}

let randId = Math.random()
setTodos(prev => [
...prev,
{
id: todos.length,
desc: inputRef.current!.value,
starred: false,
completed: false
id: randId,
...toAdd
}
])
inputRef.current!.value = ''

client.todos
.post(toAdd)
.then((res) => {
if(res.error || !res.data) {
// getting rid of the one i optimistically (prematurely) added
setTodos(prev => prev.filter((todo) => todo.id != randId))
}

if(res.data) {
const newId = res.data.id
setTodos(prev => prev.map(todo =>
todo.id === randId ? { ...todo, id: newId} : todo
))
inputRef.current!.value = ''
}
})
.catch((error) => {
// Handle errors, including timeouts
console.error('Error sending request:', error);
// Revert optimistic update (remove temporary todo)
setTodos(prev => prev.filter((todo) => todo.id != randId));
})

// setTodos([
// ...todos,
// {
// id: todos.length,
// desc: inputRef.current!.value,
// starred: false,
// completed: false
// }
// ])
// inputRef.current!.value = ''
}

return (
Expand Down