Replace the fake backend with actual API calls
This commit is contained in:
parent
dfb3d8eb5a
commit
95f8b7a8db
5 changed files with 87 additions and 111 deletions
|
@ -33,6 +33,7 @@
|
|||
"chartjs-adapter-date-fns": "^3.0.0",
|
||||
"color-alpha": "^2.0.0",
|
||||
"date-fns": "^3.6.0",
|
||||
"ky": "^1.3.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"nanoid": "^5.0.7",
|
||||
"temporal-polyfill": "^0.2.4",
|
||||
|
|
9
pnpm-lock.yaml
generated
9
pnpm-lock.yaml
generated
|
@ -38,6 +38,9 @@ importers:
|
|||
date-fns:
|
||||
specifier: ^3.6.0
|
||||
version: 3.6.0
|
||||
ky:
|
||||
specifier: ^1.3.0
|
||||
version: 1.3.0
|
||||
lodash-es:
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.21
|
||||
|
@ -965,6 +968,10 @@ packages:
|
|||
kolorist@1.8.0:
|
||||
resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
|
||||
|
||||
ky@1.3.0:
|
||||
resolution: {integrity: sha512-QUViPXlgP6NKA57IAPff/aZSmRA6qs9wKxlEpayBorwRZG+x2LG7jD4kXh8lnH3q/gkUr64NyZ7kwErUEZJmlw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
local-pkg@0.5.0:
|
||||
resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==}
|
||||
engines: {node: '>=14'}
|
||||
|
@ -2254,6 +2261,8 @@ snapshots:
|
|||
|
||||
kolorist@1.8.0: {}
|
||||
|
||||
ky@1.3.0: {}
|
||||
|
||||
local-pkg@0.5.0:
|
||||
dependencies:
|
||||
mlly: 1.7.0
|
||||
|
|
|
@ -1,14 +1,29 @@
|
|||
import { Temporal } from "temporal-polyfill"
|
||||
import { cloneDeep } from "lodash-es"
|
||||
import { fakeServerState } from "@/fakeServerState"
|
||||
import ky from "ky"
|
||||
|
||||
const api = ky.extend({
|
||||
prefixUrl: "https://ias-tea-axum.shuttleapp.rs/",
|
||||
mode: "cors"
|
||||
})
|
||||
|
||||
export interface TypeOfTea {
|
||||
id: string
|
||||
name: string
|
||||
notes: string
|
||||
waterTemperatureInCelsius: number
|
||||
steepingTime: Temporal.Duration
|
||||
registrationTimestamp: Temporal.Instant
|
||||
}
|
||||
|
||||
interface WireTypeOfTea {
|
||||
id: number
|
||||
tea_name: string
|
||||
tea_notes: string
|
||||
water_temp: number // Celsius
|
||||
steeping_seconds: number
|
||||
registration_timestamp: string
|
||||
}
|
||||
|
||||
export interface SteepingTimeChange {
|
||||
id: string
|
||||
typeOfTeaId: string
|
||||
|
@ -22,34 +37,74 @@ export interface BrewingEvent {
|
|||
timestamp: Temporal.Instant
|
||||
}
|
||||
|
||||
interface WireBrewingEvent {
|
||||
change_id: string
|
||||
tea_id: number
|
||||
steeping_seconds: number
|
||||
steeping_tested_time: string
|
||||
}
|
||||
|
||||
export interface Configuration {
|
||||
defaultSteepingTime: Temporal.Duration
|
||||
feedbackTimeout: Temporal.Duration
|
||||
}
|
||||
|
||||
interface WireConfiguration {
|
||||
default_steeping_time: number // seconds
|
||||
feedback_timeout: number // seconds
|
||||
}
|
||||
|
||||
const delay = () => new Promise(resolve => setTimeout(resolve, 1000))
|
||||
|
||||
export async function fetchConfiguration(): Promise<Configuration> {
|
||||
await delay()
|
||||
return cloneDeep(fakeServerState.configuration)
|
||||
const result = await api.get("configuration").json<WireConfiguration>()
|
||||
|
||||
return {
|
||||
defaultSteepingTime: Temporal.Duration.from({ seconds: result.default_steeping_time }).round({ largestUnit: "minutes" }),
|
||||
feedbackTimeout: Temporal.Duration.from({ seconds: result.feedback_timeout }).round({ largestUnit: "hour" }),
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateConfiguration(value: Configuration) {
|
||||
await delay()
|
||||
fakeServerState.configuration = cloneDeep(value)
|
||||
export async function updateConfiguration(data: Configuration) {
|
||||
const wireData: WireConfiguration = {
|
||||
default_steeping_time: data.defaultSteepingTime.total("seconds"),
|
||||
feedback_timeout: data.feedbackTimeout.total("seconds")
|
||||
}
|
||||
|
||||
await api.post("configuration", { json: wireData })
|
||||
}
|
||||
|
||||
export async function fetchBrewingEvents(): Promise<BrewingEvent[]> {
|
||||
await delay()
|
||||
return cloneDeep(fakeServerState.brewingEvents)
|
||||
const result = await api.get("brewing-events").json<WireBrewingEvent[]>()
|
||||
return result.map(e => ({
|
||||
id: e.change_id,
|
||||
typeOfTeaId: e.tea_id.toString(),
|
||||
timestamp: Temporal.PlainDateTime.from(e.steeping_tested_time).toZonedDateTime("UTC").toInstant()
|
||||
}))
|
||||
}
|
||||
|
||||
export async function fetchTypesOfTeaById(): Promise<Map<string, TypeOfTea>> {
|
||||
await delay()
|
||||
return new Map(fakeServerState.typesOfTea.map(t => [t.id, t]))
|
||||
const result = await api.get("types-of-tea").json<WireTypeOfTea[]>()
|
||||
|
||||
result.sort((a, b) => a.id - b.id)
|
||||
|
||||
return new Map(result.map(t => [t.id.toString(), {
|
||||
id: t.id.toString(),
|
||||
name: t.tea_name,
|
||||
notes: t.tea_notes,
|
||||
waterTemperatureInCelsius: t.water_temp,
|
||||
steepingTime: Temporal.Duration.from({ seconds: t.steeping_seconds }).round({ largestUnit: "minutes" }), // round for balancing
|
||||
registrationTimestamp: Temporal.PlainDateTime.from(t.registration_timestamp).toZonedDateTime("UTC").toInstant()
|
||||
}]))
|
||||
}
|
||||
|
||||
export async function updateTypeOfTea(id: string, data: Pick<TypeOfTea, "name" | "steepingTime">) {
|
||||
await delay()
|
||||
Object.assign(fakeServerState.typesOfTea.find(t => t.id === id)!, data)
|
||||
export async function updateTypeOfTea(id: string, data: Pick<TypeOfTea, "name" | "notes" | "waterTemperatureInCelsius" | "steepingTime">) {
|
||||
const wireData: Pick<WireTypeOfTea, "tea_name" | "tea_notes" | "water_temp" | "steeping_seconds"> = {
|
||||
tea_name: data.name,
|
||||
tea_notes: data.notes,
|
||||
water_temp: data.waterTemperatureInCelsius,
|
||||
steeping_seconds: data.steepingTime.total("seconds")
|
||||
}
|
||||
|
||||
await api.put(`types-of-tea/${id}`, { json: wireData })
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
import { Temporal } from "temporal-polyfill"
|
||||
import type { BrewingEvent, Configuration, SteepingTimeChange, TypeOfTea } from "@/backend"
|
||||
import { random } from "lodash-es"
|
||||
import { nanoid } from "nanoid"
|
||||
|
||||
const localTimeZoneId = Temporal.Now.timeZoneId()
|
||||
|
||||
const configuration: Configuration = {
|
||||
defaultSteepingTime: Temporal.Duration.from({ minutes: 4, seconds: 30 }),
|
||||
feedbackTimeout: Temporal.Duration.from({ hours: 2 })
|
||||
}
|
||||
|
||||
const typesOfTea: TypeOfTea[] = [
|
||||
{
|
||||
id: nanoid(),
|
||||
name: "Pfefferminz",
|
||||
steepingTime: Temporal.Duration.from({ minutes: 5, seconds: 20 }),
|
||||
registrationTimestamp: Temporal.ZonedDateTime.from({ timeZone: localTimeZoneId, year: 2024, month: 2, day: 20, hour: 14, minute: 24 }).toInstant()
|
||||
},
|
||||
{
|
||||
id: nanoid(),
|
||||
name: "Türkischer Apfel",
|
||||
steepingTime: Temporal.Duration.from({ minutes: 3, seconds: 50 }),
|
||||
registrationTimestamp: Temporal.ZonedDateTime.from({ timeZone: localTimeZoneId, year: 2024, month: 3, day: 1, hour: 16, minute: 1 }).toInstant()
|
||||
},
|
||||
{
|
||||
id: nanoid(),
|
||||
name: "Fenchel-Anis-Kümmel",
|
||||
steepingTime: Temporal.Duration.from({ minutes: 8 }),
|
||||
registrationTimestamp: Temporal.ZonedDateTime.from({ timeZone: localTimeZoneId, year: 2024, month: 3, day: 9, hour: 9, minute: 55 }).toInstant()
|
||||
},
|
||||
{
|
||||
id: nanoid(),
|
||||
name: "Hagebutte",
|
||||
steepingTime: Temporal.Duration.from({ minutes: 4, seconds: 30 }),
|
||||
registrationTimestamp: Temporal.ZonedDateTime.from({ timeZone: localTimeZoneId, year: 2024, month: 3, day: 29, hour: 15, minute: 34 }).toInstant()
|
||||
},
|
||||
]
|
||||
|
||||
const steepingTimeChanges: SteepingTimeChange[] = []
|
||||
const brewingEvents: BrewingEvent[] = []
|
||||
|
||||
for (const type of typesOfTea) {
|
||||
const numberOfBrewingEvents = random(5, 10)
|
||||
let nextTimestamp = type.registrationTimestamp
|
||||
let lastTwoSteepingTimeSeconds: number[] = [type.steepingTime.total({ unit: "seconds" })]
|
||||
|
||||
for (let i = 0; i < numberOfBrewingEvents; i++) {
|
||||
brewingEvents.push({
|
||||
id: nanoid(),
|
||||
typeOfTeaId: type.id,
|
||||
timestamp: nextTimestamp,
|
||||
})
|
||||
|
||||
if (random(0, 100) < 20) {
|
||||
let newSteepingTimeSeconds: number
|
||||
const direction = random(0, 1) === 1 ? "increase" : "decrease"
|
||||
const currentSeconds = lastTwoSteepingTimeSeconds[0]
|
||||
|
||||
if (lastTwoSteepingTimeSeconds.length === 1) {
|
||||
newSteepingTimeSeconds = direction === "increase" ? currentSeconds + 30 : currentSeconds - 30
|
||||
} else {
|
||||
const lastDelta = lastTwoSteepingTimeSeconds[1] - lastTwoSteepingTimeSeconds[0]
|
||||
const lastDirection = lastDelta > 0 ? "increase" : "decrease"
|
||||
if (direction === lastDirection) {
|
||||
newSteepingTimeSeconds = direction === "increase" ? currentSeconds + 30 : currentSeconds - 30
|
||||
} else {
|
||||
newSteepingTimeSeconds = Math.round(Math.abs(lastTwoSteepingTimeSeconds[0] - lastTwoSteepingTimeSeconds[1]) / 2)
|
||||
}
|
||||
}
|
||||
|
||||
steepingTimeChanges.push({
|
||||
id: nanoid(),
|
||||
typeOfTeaId: type.id,
|
||||
timestamp: nextTimestamp.add({ hours: random(0, 1), minutes: random(0, 30) }),
|
||||
newValue: Temporal.Duration.from({ seconds: newSteepingTimeSeconds })
|
||||
})
|
||||
}
|
||||
|
||||
nextTimestamp = nextTimestamp.add(Temporal.Duration.from({ hours: random(0, 14 * 24), minutes: random(0, 60) }))
|
||||
}
|
||||
}
|
||||
|
||||
brewingEvents.sort((a, b) => Temporal.Instant.compare(a.timestamp, b.timestamp))
|
||||
steepingTimeChanges.sort((a, b) => Temporal.Instant.compare(a.timestamp, b.timestamp))
|
||||
|
||||
export const fakeServerState: {
|
||||
configuration: Configuration
|
||||
typesOfTea: TypeOfTea[]
|
||||
steepingTimeChanges: SteepingTimeChange[]
|
||||
brewingEvents: BrewingEvent[]
|
||||
} = {
|
||||
configuration,
|
||||
typesOfTea,
|
||||
steepingTimeChanges,
|
||||
brewingEvents
|
||||
}
|
|
@ -19,5 +19,13 @@ export default defineConfig({
|
|||
alias: {
|
||||
"@": resolve(__dirname, "./src")
|
||||
}
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
"/api": {
|
||||
target: "http://localhost:8000",
|
||||
ws: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue