Reescrita dos geradores: biblioteca IGenerator, minimal API e novo frontend
- GeradoresService: cada tipo passa a ser um IGenerator (NIF, NIPC, NISS, CC, passaporte, IBAN, NIB, cartões, referência MB, pessoa, telefone, código postal, email, matrícula, EAN, UUID) registado em GeneratorRegistry; remove DAL/EF - GeradoresWS: minimal APIs em /api/v1 com OpenAPI + Scalar e health check - UnitTest: testes de ida e volta, valores conhecidos, detecção e API - geradoresfe: UI construída a partir dos metadados da API, validador livre, exportação CSV/JSON/TXT, nginx com API_UPSTREAM configurável - Docker, docker-compose e Jenkinsfile actualizados Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,31 +1,27 @@
|
||||
import { CheckIcon, XIcon } from "lucide-react";
|
||||
import { CopyIcon } from "lucide-react";
|
||||
import { copyToClipboard } from "../../lib/clipboard";
|
||||
|
||||
type ResultDisplayProps = {
|
||||
value: string;
|
||||
validated: boolean | null;
|
||||
onChange?: (value: string) => void;
|
||||
label: string;
|
||||
};
|
||||
|
||||
export function ResultDisplay({ value, validated, onChange }: ResultDisplayProps) {
|
||||
const baseClasses = "flex items-center gap-2 px-3 py-2 border rounded-md text-sm w-full";
|
||||
const colors =
|
||||
validated === true
|
||||
? "border-green-500 text-green-700 bg-green-50 dark:text-green-400 dark:bg-green-950 dark:border-green-700"
|
||||
: validated === false
|
||||
? "border-red-500 text-red-700 bg-red-50 dark:text-red-400 dark:bg-red-950 dark:border-red-700"
|
||||
: "border-gray-300 text-gray-700 bg-gray-100 dark:text-gray-300 dark:bg-zinc-800 dark:border-gray-600";
|
||||
|
||||
export function ResultDisplay({ value, label }: ResultDisplayProps) {
|
||||
return (
|
||||
<div className={baseClasses + " " + colors}>
|
||||
<input
|
||||
type="text"
|
||||
readOnly={!onChange}
|
||||
value={value}
|
||||
onChange={(e) => onChange?.(e.target.value)}
|
||||
className="flex-1 bg-transparent outline-none font-mono truncate"
|
||||
/>
|
||||
{validated === true && <CheckIcon className="w-5 h-5" />}
|
||||
{validated === false && <XIcon className="w-5 h-5" />}
|
||||
<div className="flex items-center gap-2 rounded-lg border border-gray-300 bg-gray-50 px-3 py-2 dark:border-zinc-600 dark:bg-zinc-800">
|
||||
<output aria-label={`${label} gerado`} className="min-h-5 flex-1 truncate font-mono text-sm text-gray-900 dark:text-gray-100">
|
||||
{value || <span className="text-gray-400">—</span>}
|
||||
</output>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyToClipboard(value, label)}
|
||||
disabled={!value}
|
||||
className="rounded p-1 text-gray-500 hover:bg-gray-200 hover:text-blue-600 disabled:opacity-30 dark:hover:bg-zinc-700"
|
||||
title="Copiar"
|
||||
aria-label="Copiar"
|
||||
>
|
||||
<CopyIcon className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user