feat: add ticket workflow pages

This commit is contained in:
hailin
2026-06-30 18:49:41 +08:00
parent c80c286227
commit d40fdad6e9
13 changed files with 467 additions and 8 deletions

View File

@@ -0,0 +1,88 @@
import * as React from 'react'
import { AppField } from '@/components/app/AppField'
import { AppPageHeader } from '@/components/app/AppPageHeader'
import { Button } from '@/components/ui/button'
import { Card, CardContent } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Select } from '@/components/ui/select'
import { Textarea } from '@/components/ui/textarea'
import { createTicket } from './api'
import type { TicketInput } from './types'
const initialForm: TicketInput = {
title: '',
description: '',
priority: 'medium',
impact_scope: '',
environment: '',
related_system: ''
}
export function TicketCreatePage() {
const [form, setForm] = React.useState<TicketInput>(initialForm)
const [error, setError] = React.useState('')
function updateField<Key extends keyof TicketInput>(field: Key, value: TicketInput[Key]) {
setForm((current) => ({ ...current, [field]: value }))
}
async function handleSubmit(event: React.FormEvent) {
event.preventDefault()
setError('')
try {
const ticket = await createTicket(form)
window.location.hash = `/tickets/${ticket.id}`
} catch (reason) {
setError(reason instanceof Error ? reason.message : '创建失败')
}
}
return (
<main className="min-h-screen bg-background p-6 text-foreground">
<div className="mx-auto max-w-4xl">
<AppPageHeader title="Create Ticket" description="Record a confirmed support request." />
<Card className="mt-4">
<CardContent>
<form className="grid gap-4" onSubmit={handleSubmit}>
<AppField label="Title">
<Input required value={form.title} onChange={(event) => updateField('title', event.target.value)} />
</AppField>
<AppField label="Description">
<Textarea
required
value={form.description}
onChange={(event) => updateField('description', event.target.value)}
/>
</AppField>
<div className="grid gap-4 md:grid-cols-2">
<AppField label="Priority">
<Select value={form.priority} onChange={(event) => updateField('priority', event.target.value as TicketInput['priority'])}>
<option value="low">Low</option>
<option value="medium">Medium</option>
<option value="high">High</option>
<option value="urgent">Urgent</option>
</Select>
</AppField>
<AppField label="Related System">
<Input value={form.related_system} onChange={(event) => updateField('related_system', event.target.value)} />
</AppField>
<AppField label="Impact Scope">
<Input value={form.impact_scope} onChange={(event) => updateField('impact_scope', event.target.value)} />
</AppField>
<AppField label="Environment">
<Input value={form.environment} onChange={(event) => updateField('environment', event.target.value)} />
</AppField>
</div>
{error ? <p className="text-sm text-danger">{error}</p> : null}
<div className="flex justify-end">
<Button type="submit">Create</Button>
</div>
</form>
</CardContent>
</Card>
</div>
</main>
)
}