feat: switch frontend indexing to code-first identifiers

This commit is contained in:
2026-04-03 16:25:11 +00:00
parent e4804128f6
commit 8208b3b27b
17 changed files with 176 additions and 158 deletions

View File

@@ -7,14 +7,14 @@ type Props = {
onClose: () => void
onSaved?: (milestone: Milestone) => void | Promise<void>
milestone?: Milestone | null
initialProjectId?: number
initialProjectCode?: string
lockProject?: boolean
}
type FormState = {
title: string
description: string
project_id: number
project_code: string
status: string
due_date: string
planned_release_date: string
@@ -23,7 +23,7 @@ type FormState = {
const emptyForm: FormState = {
title: '',
description: '',
project_id: 0,
project_code: '',
status: 'open',
due_date: '',
planned_release_date: '',
@@ -31,7 +31,7 @@ const emptyForm: FormState = {
const toDateInput = (value?: string | null) => (value ? String(value).slice(0, 10) : '')
export default function MilestoneFormModal({ isOpen, onClose, onSaved, milestone, initialProjectId, lockProject = false }: Props) {
export default function MilestoneFormModal({ isOpen, onClose, onSaved, milestone, initialProjectCode, lockProject = false }: Props) {
const [projects, setProjects] = useState<Project[]>([])
const [saving, setSaving] = useState(false)
const [form, setForm] = useState<FormState>(emptyForm)
@@ -42,11 +42,11 @@ export default function MilestoneFormModal({ isOpen, onClose, onSaved, milestone
const init = async () => {
const { data } = await api.get<Project[]>('/projects')
setProjects(data)
const defaultProjectId = milestone?.project_id || initialProjectId || data[0]?.id || 0
const defaultProjectCode = milestone?.project_code || initialProjectCode || data[0]?.project_code || ''
setForm({
title: milestone?.title || '',
description: milestone?.description || '',
project_id: defaultProjectId,
project_code: defaultProjectCode,
status: milestone?.status || 'open',
due_date: toDateInput(milestone?.due_date),
planned_release_date: toDateInput(milestone?.planned_release_date),
@@ -54,7 +54,7 @@ export default function MilestoneFormModal({ isOpen, onClose, onSaved, milestone
}
init().catch(console.error)
}, [isOpen, milestone, initialProjectId])
}, [isOpen, milestone, initialProjectCode])
const submit = async (e: React.FormEvent) => {
e.preventDefault()
@@ -63,13 +63,13 @@ export default function MilestoneFormModal({ isOpen, onClose, onSaved, milestone
const payload = {
title: form.title,
description: form.description || null,
project_id: form.project_id,
project_code: form.project_code,
status: form.status,
due_date: form.due_date || null,
planned_release_date: form.planned_release_date || null,
}
if (milestone) {
const { data } = await api.patch<Milestone>(`/milestones/${milestone.id}`, payload)
const { data } = await api.patch<Milestone>(`/milestones/${milestone.milestone_code}`, payload)
await onSaved?.(data)
} else {
const { data } = await api.post<Milestone>('/milestones', payload)
@@ -116,8 +116,8 @@ export default function MilestoneFormModal({ isOpen, onClose, onSaved, milestone
<div className="task-create-grid">
<label>
Project
<select value={form.project_id} onChange={(e) => setForm((f) => ({ ...f, project_id: Number(e.target.value) }))} disabled={lockProject}>
{projects.map((p) => <option key={p.id} value={p.id}>{p.name}</option>)}
<select value={form.project_code} onChange={(e) => setForm((f) => ({ ...f, project_code: e.target.value }))} disabled={lockProject}>
{projects.map((p) => <option key={p.id} value={p.project_code || ''}>{p.name}</option>)}
</select>
</label>