feat(web): switch ativar/desativar em promocoes e regras de desconto

Coluna "Ativa" com switch nas tabelas das duas abas (liga/desliga na
hora, sem abrir o modal) e campo Ativa no modal de edicao. Desativada,
a promocao/regra sai imediatamente do catalogo e da alcada.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 20:57:16 +00:00
parent 76cd90ae95
commit dfdcca4674

View File

@@ -11,6 +11,7 @@ import {
Select, Select,
Skeleton, Skeleton,
Space, Space,
Switch,
Table, Table,
Tabs, Tabs,
Tag, Tag,
@@ -232,6 +233,7 @@ interface PromocaoForm {
grpProd?: string; grpProd?: string;
descPct: number; descPct: number;
periodo: [dayjs.Dayjs, dayjs.Dayjs]; periodo: [dayjs.Dayjs, dayjs.Dayjs];
ativa?: boolean;
} }
function TabPromocoes() { function TabPromocoes() {
@@ -271,10 +273,20 @@ function TabPromocoes() {
grpProd: p.grpProd ?? undefined, grpProd: p.grpProd ?? undefined,
descPct: p.descPct, descPct: p.descPct,
periodo: [dayjs(p.dataInicio), dayjs(p.dataFim)], periodo: [dayjs(p.dataInicio), dayjs(p.dataFim)],
ativa: p.ativa,
}); });
setModalOpen(true); setModalOpen(true);
} }
async function toggleAtiva(p: Promocao, ativa: boolean) {
try {
await updateMutation.mutateAsync({ id: p.id, body: { ativa } });
} catch {
return; // erro já notificado pelo handler global do QueryClient
}
void msg.success(ativa ? 'Promocao ativada' : 'Promocao desativada');
}
async function handleSubmit(values: PromocaoForm) { async function handleSubmit(values: PromocaoForm) {
const [inicio, fim] = values.periodo; const [inicio, fim] = values.periodo;
try { try {
@@ -288,6 +300,7 @@ function TabPromocoes() {
descPct: values.descPct, descPct: values.descPct,
dataInicio: inicio.format('YYYY-MM-DD'), dataInicio: inicio.format('YYYY-MM-DD'),
dataFim: fim.format('YYYY-MM-DD'), dataFim: fim.format('YYYY-MM-DD'),
ativa: values.ativa ?? true,
}, },
}); });
void msg.success('Promocao atualizada'); void msg.success('Promocao atualizada');
@@ -362,6 +375,19 @@ function TabPromocoes() {
return <Tag color="green">Ativa</Tag>; return <Tag color="green">Ativa</Tag>;
}, },
}, },
{
title: 'Ativa',
width: 70,
align: 'center' as const,
render: (_: unknown, row: Promocao) => (
<Switch
size="small"
checked={row.ativa}
loading={updateMutation.isPending}
onChange={(checked) => void toggleAtiva(row, checked)}
/>
),
},
{ {
title: '', title: '',
width: 100, width: 100,
@@ -446,6 +472,9 @@ function TabPromocoes() {
optionFilterProp="label" optionFilterProp="label"
/> />
</Form.Item> </Form.Item>
<Form.Item name="ativa" label="Ativa" valuePropName="checked">
<Switch />
</Form.Item>
</Flex> </Flex>
) : ( ) : (
<> <>
@@ -509,6 +538,7 @@ interface RegraForm {
codSubgrupo?: number; codSubgrupo?: number;
descPct: number; descPct: number;
periodo: [dayjs.Dayjs, dayjs.Dayjs]; periodo: [dayjs.Dayjs, dayjs.Dayjs];
ativa?: boolean;
} }
function TabRegras() { function TabRegras() {
@@ -575,10 +605,20 @@ function TabRegras() {
codSubgrupo: r.codSubgrupo ?? undefined, codSubgrupo: r.codSubgrupo ?? undefined,
descPct: r.descPct, descPct: r.descPct,
periodo: [dayjs(r.dataInicio), dayjs(r.dataFim)], periodo: [dayjs(r.dataInicio), dayjs(r.dataFim)],
ativa: r.ativa,
}); });
setModalOpen(true); setModalOpen(true);
} }
async function toggleAtiva(r: RegraDesconto, ativa: boolean) {
try {
await updateMutation.mutateAsync({ id: r.id, body: { ativa } });
} catch {
return; // erro já notificado pelo handler global do QueryClient
}
void msg.success(ativa ? 'Regra ativada' : 'Regra desativada');
}
async function handleSubmit(values: RegraForm) { async function handleSubmit(values: RegraForm) {
const [inicio, fim] = values.periodo; const [inicio, fim] = values.periodo;
try { try {
@@ -593,6 +633,7 @@ function TabRegras() {
descPct: values.descPct, descPct: values.descPct,
dataInicio: inicio.format('YYYY-MM-DD'), dataInicio: inicio.format('YYYY-MM-DD'),
dataFim: fim.format('YYYY-MM-DD'), dataFim: fim.format('YYYY-MM-DD'),
ativa: values.ativa ?? true,
}, },
}); });
void msg.success('Regra atualizada'); void msg.success('Regra atualizada');
@@ -678,6 +719,19 @@ function TabRegras() {
return <Tag color="green">Ativa</Tag>; return <Tag color="green">Ativa</Tag>;
}, },
}, },
{
title: 'Ativa',
width: 70,
align: 'center' as const,
render: (_: unknown, row: RegraDesconto) => (
<Switch
size="small"
checked={row.ativa}
loading={updateMutation.isPending}
onChange={(checked) => void toggleAtiva(row, checked)}
/>
),
},
{ {
title: '', title: '',
width: 100, width: 100,
@@ -783,6 +837,9 @@ function TabRegras() {
optionFilterProp="label" optionFilterProp="label"
/> />
</Form.Item> </Form.Item>
<Form.Item name="ativa" label="Ativa" valuePropName="checked">
<Switch />
</Form.Item>
</Flex> </Flex>
) : ( ) : (
<> <>