feat: fetch services from Supabase instead of static mock data

This commit is contained in:
belviskhoremk
2026-08-12 20:12:53 +02:00
parent 063874b60c
commit a0e8a2ca60
2 changed files with 82 additions and 6 deletions

58
src/data/services.test.ts Normal file
View File

@@ -0,0 +1,58 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
const orderMock = vi.fn()
const selectMock = vi.fn(() => ({ order: orderMock }))
const fromMock = vi.fn<(...args: unknown[]) => { select: typeof selectMock }>(() => ({ select: selectMock }))
const resolveImageUrlMock = vi.fn((path: string) => `https://cdn.example/${path}`)
vi.mock('../lib/supabase', () => ({
supabase: { from: (...args: unknown[]) => fromMock(...args) },
}))
vi.mock('../lib/resolveImageUrl', () => ({
resolveImageUrl: (path: string) => resolveImageUrlMock(path),
}))
const ROW = {
id: 'knotless',
name: 'Tresses sans nœuds',
duration_minutes: 240,
price_from: 150,
description: 'Tresses sans tension.',
image: 'styles/knotless.jpg',
}
import { fetchServices, type Service } from './services'
describe('fetchServices', () => {
beforeEach(() => {
orderMock.mockReset()
selectMock.mockClear()
fromMock.mockClear()
resolveImageUrlMock.mockClear()
})
it('fetches services ordered by name and maps snake_case columns to the Service shape', async () => {
orderMock.mockResolvedValue({ data: [ROW], error: null })
const services = await fetchServices()
expect(fromMock).toHaveBeenCalledWith('services')
expect(orderMock).toHaveBeenCalledWith('name')
expect(resolveImageUrlMock).toHaveBeenCalledWith('styles/knotless.jpg')
expect(services).toEqual<Service[]>([
{
id: 'knotless',
name: 'Tresses sans nœuds',
durationMinutes: 240,
priceFrom: 150,
description: 'Tresses sans tension.',
image: 'https://cdn.example/styles/knotless.jpg',
},
])
})
it('throws when the fetch fails', async () => {
orderMock.mockResolvedValue({ data: null, error: { message: 'network error' } })
await expect(fetchServices()).rejects.toEqual({ message: 'network error' })
})
})

View File

@@ -1,3 +1,6 @@
import { supabase } from '../lib/supabase'
import { resolveImageUrl } from '../lib/resolveImageUrl'
export interface Service {
id: string
name: string
@@ -7,9 +10,24 @@ export interface Service {
image: string
}
export const services: Service[] = [
{ id: 'knotless', name: 'Tresses sans nœuds', durationMinutes: 240, priceFrom: 150, description: 'Tresses sans tension avec une racine naturelle et invisible.', image: '/styles/knotless.jpg' },
{ id: 'boho', name: 'Tresses Boho', durationMinutes: 270, priceFrom: 180, description: 'Tresses sans nœuds agrémentées de mèches bouclées pour un look doux et romantique.', image: '/styles/boho.jpg' },
{ id: 'locs', name: 'Faux Locs', durationMinutes: 300, priceFrom: 200, description: 'Locs légères à l\'allure naturelle, installées avec soin.', image: '/styles/locs.jpg' },
{ id: 'cornrows', name: 'Nattes Collées', durationMinutes: 120, priceFrom: 90, description: 'Nattes collées classiques et nettes, droites vers l\'arrière ou avec un motif personnalisé.', image: '/styles/cornrows.jpg' },
]
interface ServiceRow {
id: string
name: string
duration_minutes: number
price_from: number
description: string
image: string
}
export async function fetchServices(): Promise<Service[]> {
const { data, error } = await supabase.from('services').select('*').order('name')
if (error) throw error
return ((data ?? []) as ServiceRow[]).map((row) => ({
id: row.id,
name: row.name,
durationMinutes: row.duration_minutes,
priceFrom: row.price_from,
description: row.description,
image: resolveImageUrl(row.image),
}))
}