import { Link, useForm } from '@inertiajs/react';
import { useRef } from 'react';
import { Panel, controlClass } from '@/components/procurement';
import { Button } from '@/components/ui/button';
type Payload = {
title: string;
received_on: string | null;
source_reference: string;
statement: string;
};
type Decision = {
outcome: string;
reason: string;
follow_up: string;
response_reference: string;
};
type Record = {
id: number;
version: number;
status: string;
payload: Payload;
decision: Decision | null;
created_by: number;
reviewed_by: number | null;
reviewed_at: string | null;
review_reason: string | null;
canEdit: boolean;
canReview: boolean;
};
type History = {
id: number;
user_id: number;
action: string;
created_at: string;
after: Record;
};
export type ResponseData = {
ready: boolean;
canCreate: boolean;
records: Record[];
history: {
data: History[];
total: number;
prev_page_url: string | null;
next_page_url: string | null;
} | null;
};
const states: { [key: string]: string } = {
draft: 'Em preparação',
review: 'Em análise',
returned: 'Devolvido para completar',
decided: 'Conclusão registada',
};
const outcomes: { [key: string]: string } = {
accepted: 'Argumentos acolhidos',
partially_accepted: 'Argumentos parcialmente acolhidos',
not_accepted: 'Argumentos não acolhidos',
};
const actions: { [key: string]: string } = {
create: 'Registo',
save: 'Alteração',
submit: 'Submissão para análise',
return: 'Devolução',
decide: 'Conclusão independente',
};
const empty: Payload = {
title: '',
received_on: '',
source_reference: '',
statement: '',
};
function Errors({ errors }: { errors: { [key: string]: string } }) {
return Object.keys(errors).length ? (
{Object.entries(errors).map(([key, message]) => (
{message}
))}
) : null;
}
function Fields({
payload,
change,
}: {
payload: Payload;
change: (key: keyof Payload, value: string) => void;
}) {
return (
Assunto
change('title', e.target.value)}
/>
Recebido em
change('received_on', e.target.value)}
/>
Documento ou origem recebida
Argumentos apresentados pelo fornecedor
);
}
function ResponseCard({
record: r,
base,
names,
}: {
record: Record;
base: string;
names: { [key: number]: string };
}) {
const edit = useForm({ version: r.version, payload: r.payload });
const submit = useForm({ version: r.version });
const review = useForm({
version: r.version,
outcome: '',
reason: '',
follow_up: '',
response_reference: '',
});
const url = `${base}/${r.id}`;
const dirty =
JSON.stringify(edit.data.payload) !== JSON.stringify(r.payload);
return (
CTR-{r.id} · {r.payload.title}
{states[r.status]} · Versão {r.version} · Registado por{' '}
{names[r.created_by] ?? `#${r.created_by}`}
{r.canEdit ? (
) : (
Recebido em:{' '}
{r.payload.received_on || 'Ainda não indicado'}
Documento/origem:{' '}
{r.payload.source_reference || 'Ainda não indicado'}
{r.payload.statement ||
'Argumentos ainda não transcritos.'}
)}
{r.review_reason && (
Última análise por{' '}
{names[r.reviewed_by ?? 0] ?? `#${r.reviewed_by}`}
{r.reviewed_at
? ` em ${new Date(r.reviewed_at).toLocaleString('pt-MZ')}`
: ''}
: {r.review_reason}
)}
{r.decision && (
{outcomes[r.decision.outcome]}
{r.decision.follow_up && (
Seguimento: {r.decision.follow_up}
)}
{r.decision.response_reference && (
Referência da resposta:{' '}
{r.decision.response_reference}
)}
)}
{r.canReview && (
Conclusão
review.setData('outcome', e.target.value)
}
>
Escolher conclusão
{Object.entries(outcomes).map(([key, label]) => (
{label}
))}
Análise fundamentada
Seguimento a dar
Referência da resposta preparada (opcional)
review.setData(
'response_reference',
e.target.value,
)
}
/>
{
review.transform((values) => values);
review.post(url + '/decide', {
preserveState: 'errors',
preserveScroll: true,
});
}}
>
Registar conclusão da análise
{
review.transform((values) => ({
version: values.version,
reason: values.reason,
}));
review.post(url + '/return', {
preserveState: 'errors',
preserveScroll: true,
});
}}
>
Devolver para completar
)}
);
}
export default function SupplierResponses({
data,
evaluationId,
names,
reportOnly,
generatedAt,
}: {
data: ResponseData;
evaluationId: number;
names: { [key: number]: string };
reportOnly: boolean;
generatedAt: string;
}) {
const create = useForm({ payload: empty });
const operation = useRef(null);
const base = `/fornecedores/avaliacoes/${evaluationId}/contraditorios`;
return (
Documentos e argumentos recebidos, registados pela equipa.
Acompanhamento consultado em{' '}
{new Date(generatedAt).toLocaleString('pt-MZ')}. A conclusão
fica registada para comunicação ao fornecedor; a avaliação
aprovada conserva-se e qualquer rectificação exige uma nova
revisão.
{!data.ready ? (
A instalação do contraditório ainda não está concluída.
) : (
<>
{!data.records.length && (
Sem contraditórios registados nesta revisão.
)}
{data.records.map((r) => (
))}
{data.canCreate && (
Registar documento recebido
)}
{!reportOnly &&
data.history &&
data.history.total > 0 && (
Histórico do contraditório (
{data.history.total})
{data.history.data.map((event) => (
CTR-{event.after.id} ·{' '}
{actions[
event.action.split(
'.',
)[1]
] ?? event.action}{' '}
·{' '}
{names[event.user_id] ??
`#${event.user_id}`}{' '}
·{' '}
{new Date(
event.created_at,
).toLocaleString('pt-MZ')}
{
event.after.payload
.title
}{' '}
·{' '}
{
states[
event.after
.status
]
}{' '}
· Versão{' '}
{event.after.version}
Recebido:{' '}
{event.after.payload
.received_on ||
'Não indicado'}
{
event.after.payload
.source_reference
}
{
event.after.payload
.statement
}
{event.after
.review_reason && (
Análise:{' '}
{
event.after
.review_reason
}
)}
{event.after.decision && (
<>
{
outcomes[
event
.after
.decision
.outcome
]
}
{
event.after
.decision
.follow_up
}
{
event.after
.decision
.response_reference
}
>
)}
))}
{data.history.prev_page_url && (
Anterior
)}
{data.history.next_page_url && (
Seguinte
)}
)}
>
)}
);
}