Ticket IDs, audit log, markdown comments, tabbed detail page
- Tickets get a random display ID (V + 9 digits, e.g. V325813929) - Ticket detail page has Overview / Comments / Audit Log tabs - Audit log records every action (create, status, assignee, severity, reroute, title/overview edit, comment add/delete) with who and when - Comments redesigned: avatar (initials + color), markdown rendering via react-markdown + remark-gfm, Write/Preview toggle - Dashboard shows displayId and assignee avatar - URLs now use displayId (/tickets/V325813929) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
const PALETTE = [
|
||||
'#ef4444', '#f97316', '#f59e0b', '#10b981',
|
||||
'#06b6d4', '#3b82f6', '#8b5cf6', '#ec4899',
|
||||
]
|
||||
|
||||
function nameToColor(name: string): string {
|
||||
let hash = 0
|
||||
for (let i = 0; i < name.length; i++) {
|
||||
hash = name.charCodeAt(i) + ((hash << 5) - hash)
|
||||
}
|
||||
return PALETTE[Math.abs(hash) % PALETTE.length]
|
||||
}
|
||||
|
||||
function initials(name: string): string {
|
||||
return name
|
||||
.split(' ')
|
||||
.slice(0, 2)
|
||||
.map((n) => n[0])
|
||||
.join('')
|
||||
.toUpperCase()
|
||||
}
|
||||
|
||||
const SIZES = {
|
||||
sm: 'w-6 h-6 text-xs',
|
||||
md: 'w-8 h-8 text-sm',
|
||||
lg: 'w-10 h-10 text-base',
|
||||
}
|
||||
|
||||
interface AvatarProps {
|
||||
name: string
|
||||
size?: keyof typeof SIZES
|
||||
}
|
||||
|
||||
export default function Avatar({ name, size = 'md' }: AvatarProps) {
|
||||
return (
|
||||
<div
|
||||
className={`${SIZES[size]} rounded-full flex items-center justify-center font-semibold text-white flex-shrink-0 select-none`}
|
||||
style={{ backgroundColor: nameToColor(name) }}
|
||||
title={name}
|
||||
>
|
||||
{initials(name)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user