Skip to content

Commit

Permalink
refactor code to have api and database module
Browse files Browse the repository at this point in the history
  • Loading branch information
ligsnf committed Dec 17, 2024
1 parent 6723d06 commit 39d6860
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 97 deletions.
45 changes: 45 additions & 0 deletions src/api/results.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { db } from "@/db/local-storage"
import { Result } from "@/schemas/result-schema"

export function addResult() {
const currentData = db.getData()
const maxId = Math.max(...currentData.map(item => item.id), -1)
const newResult: Result = {
id: maxId + 1,
unitCode: "",
creditPoints: 6,
mark: 0,
grade: "N",
}
return db.setData([...currentData, newResult])
}

export function updateResult(id: number, updatedResult: Result) {
const currentData = db.getData()
const newData = currentData.map(item =>
item.id === id ? { ...updatedResult, id } : item
)
return db.setData(newData)
}

export function deleteResult(id: number) {
const currentData = db.getData()
const newData = currentData.filter(item => item.id !== id)
return db.setData(newData)
}

export function restoreResult(itemToRestore: Result) {
const currentData = db.getData()
if (currentData.some(item => item.id === itemToRestore.id)) {
return currentData
}

const insertIndex = currentData.findIndex(item => item.id > itemToRestore.id)
const newData = [...currentData]
if (insertIndex === -1) {
newData.push(itemToRestore)
} else {
newData.splice(insertIndex, 0, itemToRestore)
}
return db.setData(newData)
}
59 changes: 59 additions & 0 deletions src/db/local-storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Result } from "@/schemas/result-schema"
import { STORAGE_KEYS } from "@/constants/storage-keys"

const initialData: Result[] = [
{
id: 0,
unitCode: "ECE2072",
creditPoints: 6,
mark: 50,
grade: "P",
},
{
id: 1,
unitCode: "FIT2107",
creditPoints: 6,
mark: 64,
grade: "C",
},
{
id: 2,
unitCode: "FIT3170",
creditPoints: 12,
mark: 77,
grade: "D",
},
{
id: 3,
unitCode: "FIT2095",
creditPoints: 6,
mark: 99,
grade: "HD",
},
]

export function localStorage<T>(key: string, initialValue: T) {
const getData = (): T => {
try {
const item = window.localStorage.getItem(key)
return item ? JSON.parse(item) as T : initialValue
} catch (error) {
console.warn(`Error reading localStorage key "${key}":`, error)
return initialValue
}
}

const setData = (value: T): T => {
try {
window.localStorage.setItem(key, JSON.stringify(value))
return value
} catch (error) {
console.warn(`Error setting localStorage key "${key}":`, error)
return value
}
}

return { getData, setData }
}

export const db = localStorage<Result[]>(STORAGE_KEYS.RESULTS, initialData)
25 changes: 0 additions & 25 deletions src/hooks/use-local-storage.ts

This file was deleted.

90 changes: 18 additions & 72 deletions src/routes/index.lazy.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useMemo, useState } from 'react'
import { useEffect, useMemo, useState } from 'react'
import { toast } from "sonner"
import { createLazyFileRoute } from '@tanstack/react-router'
import { useLocalStorage } from '@/hooks/use-local-storage'
import { STORAGE_KEYS } from '@/constants/storage-keys'
import { calculateWAM, calculateGPA, calculateTotalCredits } from "@/lib/calculate"
import { addResult, deleteResult, updateResult, restoreResult } from '@/api/results'
import { db } from "@/db/local-storage"
import { Result } from "@/schemas/result-schema"
import { toast } from "sonner"
import { calculateWAM, calculateGPA, calculateTotalCredits } from "@/lib/calculate"

import { StatCard } from "@/components/stat-card"
import { CSVUploadAlert } from "@/components/csv/csv-upload-alert"
Expand All @@ -21,72 +21,27 @@ export const Route = createLazyFileRoute('/')({
component: Index,
})

const initialData: Result[] = [
{
id: 0,
unitCode: "ECE2072",
creditPoints: 6,
mark: 50,
grade: "P",
},
{
id: 1,
unitCode: "FIT2107",
creditPoints: 6,
mark: 64,
grade: "C",
},
{
id: 2,
unitCode: "FIT3170",
creditPoints: 12,
mark: 77,
grade: "D",
},
{
id: 3,
unitCode: "FIT2095",
creditPoints: 6,
mark: 99,
grade: "HD",
},
]

function Index() {
const [data, setData] = useLocalStorage<Result[]>(STORAGE_KEYS.RESULTS, initialData)
const [data, setData] = useState<Result[]>(() => db.getData())
const [, setDeletedItems] = useState<Map<number, Result>>(() => new Map<number, Result>())

const handleResultAdd = () => {
const maxId = Math.max(...data.map(item => item.id), -1)
const newResult: Result = {
id: maxId + 1,
unitCode: "",
creditPoints: 6,
mark: 0,
grade: "N",
}
setData([...data, newResult])
}

const handleResultUpdate = (id: number, updatedResult: Result) => {
setData(data.map(item =>
item.id === id ? { ...updatedResult, id } : item
))
}
useEffect(() => {
setData(db.getData())
}, [])

const handleResultDelete = (id: number) => {
const itemToDelete = data.find(item => item.id === id)
if (!itemToDelete) return

// Store deleted item with its ID

const newData = deleteResult(id)
setData(newData)

setDeletedItems((prev: Map<number, Result>) => {
const newMap = new Map(prev)
newMap.set(id, itemToDelete)
return newMap
})

setData(prev => prev.filter(item => item.id !== id))


toast.warning("Unit has been deleted", {
description: (
<pre className="mt-1 rounded bg-muted px-2 py-1 font-mono text-sm">
Expand All @@ -100,17 +55,8 @@ function Index() {
const newMap = new Map(prev)
const itemToRestore = newMap.get(id)
if (itemToRestore) {
// Restore at original position based on ID
setData(prevData => {
const newData = [...prevData]
const insertIndex = newData.findIndex(item => item.id > itemToRestore.id)
if (insertIndex === -1) {
newData.push(itemToRestore)
} else {
newData.splice(insertIndex, 0, itemToRestore)
}
return newData
})
const newData = restoreResult(itemToRestore)
setData(newData)
newMap.delete(id)
}
return newMap
Expand Down Expand Up @@ -178,12 +124,12 @@ function Index() {
<div className="container mx-auto py-4">
<ResultTable
data={data}
onResultUpdate={handleResultUpdate}
onResultUpdate={(id, result) => setData(updateResult(id, result))}
onResultDelete={handleResultDelete}
/>
</div>
<div className="container mx-auto md:mt-2">
<Button onClick={handleResultAdd}>Add Unit</Button>
<Button onClick={() => setData(addResult())}>Add Unit</Button>
</div>
</div>
)
Expand Down

0 comments on commit 39d6860

Please sign in to comment.