Keep/keep-notes/context/LabelContext.tsx
sepehr 7fb486c9a4 feat: Complete internationalization and code cleanup
## Translation Files
- Add 11 new language files (es, de, pt, ru, zh, ja, ko, ar, hi, nl, pl)
- Add 100+ missing translation keys across all 15 languages
- New sections: notebook, pagination, ai.batchOrganization, ai.autoLabels
- Update nav section with workspace, quickAccess, myLibrary keys

## Component Updates
- Update 15+ components to use translation keys instead of hardcoded text
- Components: notebook dialogs, sidebar, header, note-input, ghost-tags, etc.
- Replace 80+ hardcoded English/French strings with t() calls
- Ensure consistent UI across all supported languages

## Code Quality
- Remove 77+ console.log statements from codebase
- Clean up API routes, components, hooks, and services
- Keep only essential error handling (no debugging logs)

## UI/UX Improvements
- Update Keep logo to yellow post-it style (from-yellow-400 to-amber-500)
- Change selection colors to #FEF3C6 (notebooks) and #EFB162 (nav items)
- Make "+" button permanently visible in notebooks section
- Fix grammar and syntax errors in multiple components

## Bug Fixes
- Fix JSON syntax errors in it.json, nl.json, pl.json, zh.json
- Fix syntax errors in notebook-suggestion-toast.tsx
- Fix syntax errors in use-auto-tagging.ts
- Fix syntax errors in paragraph-refactor.service.ts
- Fix duplicate "fusion" section in nl.json

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

Ou une version plus courte si vous préférez :

feat(i18n): Add 15 languages, remove logs, update UI components

- Create 11 new translation files (es, de, pt, ru, zh, ja, ko, ar, hi, nl, pl)
- Add 100+ translation keys: notebook, pagination, AI features
- Update 15+ components to use translations (80+ strings)
- Remove 77+ console.log statements from codebase
- Fix JSON syntax errors in 4 translation files
- Fix component syntax errors (toast, hooks, services)
- Update logo to yellow post-it style
- Change selection colors (#FEF3C6, #EFB162)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-11 22:26:13 +01:00

147 lines
4.1 KiB
TypeScript

'use client'
import { createContext, useContext, useState, useEffect, ReactNode } from 'react'
import { LabelColorName, LABEL_COLORS } from '@/lib/types'
import { getHashColor } from '@/lib/utils'
export interface Label {
id: string
name: string
color: LabelColorName
userId?: string | null
createdAt: Date
updatedAt: Date
}
interface LabelContextType {
labels: Label[]
loading: boolean
notebookId?: string | null
setNotebookId: (notebookId: string | null) => void
addLabel: (name: string, color?: LabelColorName, notebookId?: string | null) => 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)
const [notebookId, setNotebookId] = useState<string | null>(null)
const fetchLabels = async () => {
try {
setLoading(true)
// Build URL with notebookId filter
const url = new URL('/api/labels', window.location.origin)
if (notebookId) {
url.searchParams.set('notebookId', notebookId)
}
const response = await fetch(url.toString(), {
cache: 'no-store',
credentials: 'include'
})
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)
}
}
// Re-fetch labels when notebookId changes
useEffect(() => {
fetchLabels()
}, [notebookId])
const addLabel = async (name: string, color?: LabelColorName, labelNotebookId?: string | null) => {
try {
const labelColor = color || getHashColor(name);
const finalNotebookId = labelNotebookId || notebookId
const response = await fetch('/api/labels', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, color: labelColor, notebookId: finalNotebookId }),
})
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.toLowerCase() === name.toLowerCase())
return label?.color || 'gray'
}
const refreshLabels = async () => {
await fetchLabels()
}
const value: LabelContextType = {
labels,
loading,
notebookId,
setNotebookId,
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
}