feat: implement label management with color filtering
This commit is contained in:
133
keep-notes/context/LabelContext.tsx
Normal file
133
keep-notes/context/LabelContext.tsx
Normal file
@@ -0,0 +1,133 @@
|
||||
'use client'
|
||||
|
||||
import { createContext, useContext, useState, useEffect, ReactNode } from 'react'
|
||||
import { LabelColorName, LABEL_COLORS } from '@/lib/types'
|
||||
|
||||
export interface Label {
|
||||
id: string
|
||||
name: string
|
||||
color: LabelColorName
|
||||
userId?: string | null
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
interface LabelContextType {
|
||||
labels: Label[]
|
||||
loading: boolean
|
||||
addLabel: (name: string, color?: LabelColorName) => Promise<void>
|
||||
updateLabel: (id: string, updates: Partial<Pick<Label, 'name' | 'color'>>) => Promise<void>
|
||||
deleteLabel: (id: string) => Promise<void>
|
||||
getLabelColor: (name: string) => LabelColorName
|
||||
refreshLabels: () => Promise<void>
|
||||
}
|
||||
|
||||
const LabelContext = createContext<LabelContextType | undefined>(undefined)
|
||||
|
||||
export function LabelProvider({ children }: { children: ReactNode }) {
|
||||
const [labels, setLabels] = useState<Label[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
// Fetch labels from API
|
||||
const fetchLabels = async () => {
|
||||
try {
|
||||
setLoading(true)
|
||||
const response = await fetch('/api/labels')
|
||||
const data = await response.json()
|
||||
if (data.success && data.data) {
|
||||
setLabels(data.data)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch labels:', error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
fetchLabels()
|
||||
}, [])
|
||||
|
||||
const addLabel = async (name: string, color?: LabelColorName) => {
|
||||
try {
|
||||
// Get existing label color if not provided
|
||||
const existingColor = getLabelColorHelper(name)
|
||||
const labelColor = color || existingColor
|
||||
|
||||
const response = await fetch('/api/labels', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ name, color: labelColor }),
|
||||
})
|
||||
const data = await response.json()
|
||||
if (data.success && data.data) {
|
||||
setLabels(prev => [...prev, data.data])
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to add label:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
const updateLabel = async (id: string, updates: Partial<Pick<Label, 'name' | 'color'>>) => {
|
||||
try {
|
||||
const response = await fetch(`/api/labels/${id}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(updates),
|
||||
})
|
||||
const data = await response.json()
|
||||
if (data.success && data.data) {
|
||||
setLabels(prev => prev.map(label =>
|
||||
label.id === id ? { ...label, ...data.data } : label
|
||||
))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to update label:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
const deleteLabel = async (id: string) => {
|
||||
try {
|
||||
const response = await fetch(`/api/labels/${id}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
if (response.ok) {
|
||||
setLabels(prev => prev.filter(label => label.id !== id))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to delete label:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
const getLabelColorHelper = (name: string): LabelColorName => {
|
||||
const label = labels.find(l => l.name === name)
|
||||
return label?.color || 'gray'
|
||||
}
|
||||
|
||||
const refreshLabels = async () => {
|
||||
await fetchLabels()
|
||||
}
|
||||
|
||||
const value: LabelContextType = {
|
||||
labels,
|
||||
loading,
|
||||
addLabel,
|
||||
updateLabel,
|
||||
deleteLabel,
|
||||
getLabelColor: getLabelColorHelper,
|
||||
refreshLabels,
|
||||
}
|
||||
|
||||
return <LabelContext.Provider value={value}>{children}</LabelContext.Provider>
|
||||
}
|
||||
|
||||
export function useLabels() {
|
||||
const context = useContext(LabelContext)
|
||||
if (context === undefined) {
|
||||
throw new Error('useLabels must be used within a LabelProvider')
|
||||
}
|
||||
return context
|
||||
}
|
||||
Reference in New Issue
Block a user