Files
temetro/.agents/skills/ai-elements/scripts/code-block.tsx
T
Khalid Abdi 929bec8f31 feat: AI-added records save with placeholders + "Added by AI" provenance
Stop blocking AI imports/proposals on missing non-critical fields. Records
the chat agent drafts now save with safe placeholders, auto-generated file
numbers, and a source="ai" marker that surfaces an "Added by AI" badge so a
clinician can review/edit them later.

Backend:
- add `source` (manual|ai) column to patients/appointments/prescriptions
  (migration 0014) + canonical types, services, validation schemas
- relax patient/appointment validation: empty file number allowed, demographic
  + type/provider/initials fall back to placeholders (initials derived from name)
- patients.generateFileNumber() auto-assigns an MRN when one is missing
- proposeAppointment accepts a name when no file number resolves; AI commits +
  /api/ai/import stamp source="ai"

Frontend:
- `source` on Appointment/Patient/Prescription types; AI commits send source="ai"
- reusable <AiBadge> shown on the Patients table/detail and prescriptions list

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 19:27:17 +03:00

121 lines
2.9 KiB
TypeScript

"use client";
import {
CodeBlock,
CodeBlockActions,
CodeBlockCopyButton,
CodeBlockFilename,
CodeBlockHeader,
CodeBlockLanguageSelector,
CodeBlockLanguageSelectorContent,
CodeBlockLanguageSelectorItem,
CodeBlockLanguageSelectorTrigger,
CodeBlockLanguageSelectorValue,
CodeBlockTitle,
} from "@/components/ai-elements/code-block";
import { FileIcon } from "lucide-react";
import { useCallback, useState } from "react";
import type { BundledLanguage } from "shiki";
const codeExamples = {
go: {
code: `package main
import "fmt"
func greet(name string) string {
return fmt.Sprintf("Hello, %s!", name)
}
func main() {
fmt.Println(greet("World"))
}`,
filename: "greet.go",
},
python: {
code: `def greet(name: str) -> str:
return f"Hello, {name}!"
print(greet("World"))`,
filename: "greet.py",
},
rust: {
code: `fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
fn main() {
println!("{}", greet("World"));
}`,
filename: "greet.rs",
},
typescript: {
code: `function greet(name: string): string {
return \`Hello, \${name}!\`;
}
console.log(greet("World"));`,
filename: "greet.ts",
},
} as const;
type Language = keyof typeof codeExamples;
const languages: { value: Language; label: string }[] = [
{ label: "TypeScript", value: "typescript" },
{ label: "Python", value: "python" },
{ label: "Rust", value: "rust" },
{ label: "Go", value: "go" },
];
const handleCopy = () => {
console.log("Copied code to clipboard");
};
const handleCopyError = () => {
console.error("Failed to copy code to clipboard");
};
const Example = () => {
const [language, setLanguage] = useState<Language>("typescript");
const { code, filename } = codeExamples[language];
const handleLanguageChange = useCallback((value: string) => {
setLanguage(value as Language);
}, []);
return (
<CodeBlock code={code} language={language as BundledLanguage}>
<CodeBlockHeader>
<CodeBlockTitle>
<FileIcon size={14} />
<CodeBlockFilename>{filename}</CodeBlockFilename>
</CodeBlockTitle>
<CodeBlockActions>
<CodeBlockLanguageSelector
onValueChange={handleLanguageChange}
value={language}
>
<CodeBlockLanguageSelectorTrigger>
<CodeBlockLanguageSelectorValue />
</CodeBlockLanguageSelectorTrigger>
<CodeBlockLanguageSelectorContent>
{languages.map((lang) => (
<CodeBlockLanguageSelectorItem
key={lang.value}
value={lang.value}
>
{lang.label}
</CodeBlockLanguageSelectorItem>
))}
</CodeBlockLanguageSelectorContent>
</CodeBlockLanguageSelector>
<CodeBlockCopyButton onCopy={handleCopy} onError={handleCopyError} />
</CodeBlockActions>
</CodeBlockHeader>
</CodeBlock>
);
};
export default Example;