fix: corrige tipo JSON para String no SQLite e acentuação nos textos
- Altera typePreferences e categoryPreferences de Json para String no Prisma - Atualiza API de preferências para fazer parse/stringify de JSON - Corrige todos os textos sem acentuação nos componentes de notificação 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
f2c0298285
commit
7ecb4c1110
7 changed files with 104 additions and 89 deletions
|
|
@ -462,11 +462,11 @@ model NotificationPreferences {
|
|||
|
||||
// Preferências por tipo de notificação (JSON)
|
||||
// Ex: { "ticket_created": true, "ticket_resolved": true, "comment_public": false }
|
||||
typePreferences Json @default("{}")
|
||||
typePreferences String @default("{}")
|
||||
|
||||
// Preferências por categoria de ticket (JSON)
|
||||
// Ex: { "category_id_1": true, "category_id_2": false }
|
||||
categoryPreferences Json @default("{}")
|
||||
categoryPreferences String @default("{}")
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
|
|
|||
|
|
@ -80,10 +80,17 @@ export async function GET(_request: NextRequest) {
|
|||
? Object.keys(NOTIFICATION_TYPES)
|
||||
: COLLABORATOR_VISIBLE_TYPES
|
||||
|
||||
// Parse JSON strings
|
||||
const typePrefs: Record<string, boolean> = prefs!.typePreferences
|
||||
? JSON.parse(prefs!.typePreferences as string)
|
||||
: {}
|
||||
const catPrefs = prefs!.categoryPreferences
|
||||
? JSON.parse(prefs!.categoryPreferences as string)
|
||||
: {}
|
||||
|
||||
// Monta resposta com configuração de cada tipo
|
||||
const typeConfigs = availableTypes.map((type) => {
|
||||
const config = NOTIFICATION_TYPES[type as NotificationType]
|
||||
const typePrefs = prefs!.typePreferences as Record<string, boolean>
|
||||
const enabled = typePrefs[type] ?? config.defaultEnabled
|
||||
|
||||
return {
|
||||
|
|
@ -104,7 +111,7 @@ export async function GET(_request: NextRequest) {
|
|||
timezone: prefs.timezone,
|
||||
digestFrequency: prefs.digestFrequency,
|
||||
types: typeConfigs,
|
||||
categoryPreferences: prefs.categoryPreferences,
|
||||
categoryPreferences: catPrefs,
|
||||
isStaff,
|
||||
})
|
||||
} catch (error) {
|
||||
|
|
@ -194,11 +201,19 @@ export async function PUT(request: NextRequest) {
|
|||
quietHoursEnd: quietHoursEnd ?? null,
|
||||
timezone: timezone ?? "America/Sao_Paulo",
|
||||
digestFrequency: digestFrequency ?? "immediate",
|
||||
typePreferences: validatedTypePrefs,
|
||||
categoryPreferences: categoryPreferences ?? {},
|
||||
typePreferences: JSON.stringify(validatedTypePrefs),
|
||||
categoryPreferences: JSON.stringify(categoryPreferences ?? {}),
|
||||
},
|
||||
})
|
||||
} else {
|
||||
// Parse existing JSON strings
|
||||
const existingTypePrefs = existingPrefs.typePreferences
|
||||
? JSON.parse(existingPrefs.typePreferences as string)
|
||||
: {}
|
||||
const existingCatPrefs = existingPrefs.categoryPreferences
|
||||
? JSON.parse(existingPrefs.categoryPreferences as string)
|
||||
: {}
|
||||
|
||||
// Atualiza preferências existentes
|
||||
await prisma.notificationPreferences.update({
|
||||
where: { userId },
|
||||
|
|
@ -208,11 +223,11 @@ export async function PUT(request: NextRequest) {
|
|||
quietHoursEnd: quietHoursEnd !== undefined ? quietHoursEnd : existingPrefs.quietHoursEnd,
|
||||
timezone: timezone ?? existingPrefs.timezone,
|
||||
digestFrequency: digestFrequency ?? existingPrefs.digestFrequency,
|
||||
typePreferences: {
|
||||
...(existingPrefs.typePreferences as Record<string, boolean>),
|
||||
typePreferences: JSON.stringify({
|
||||
...existingTypePrefs,
|
||||
...validatedTypePrefs,
|
||||
},
|
||||
categoryPreferences: categoryPreferences ?? existingPrefs.categoryPreferences,
|
||||
}),
|
||||
categoryPreferences: JSON.stringify(categoryPreferences ?? existingCatPrefs),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import { NotificationPreferencesForm } from "@/components/settings/notification-
|
|||
import { requireAuthenticatedSession } from "@/lib/auth-server"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Preferencias de notificacao",
|
||||
description: "Configure quais notificacoes por e-mail deseja receber.",
|
||||
title: "Preferências de notificação",
|
||||
description: "Configure quais notificações por e-mail deseja receber.",
|
||||
}
|
||||
|
||||
export default async function PortalNotificationSettingsPage() {
|
||||
|
|
@ -14,7 +14,7 @@ export default async function PortalNotificationSettingsPage() {
|
|||
const role = (session.user.role ?? "").toLowerCase()
|
||||
const persona = (session.user.machinePersona ?? "").toLowerCase()
|
||||
|
||||
// Colaboradores e maquinas com persona de colaborador podem acessar
|
||||
// Colaboradores e máquinas com persona de colaborador podem acessar
|
||||
const allowedRoles = new Set(["collaborator", "manager", "admin", "agent"])
|
||||
const isMachinePersonaAllowed = role === "machine" && (persona === "collaborator" || persona === "manager")
|
||||
const allowed = allowedRoles.has(role) || isMachinePersonaAllowed
|
||||
|
|
@ -23,7 +23,7 @@ export default async function PortalNotificationSettingsPage() {
|
|||
redirect("/portal")
|
||||
}
|
||||
|
||||
// Staff deve usar a pagina de configuracoes completa
|
||||
// Staff deve usar a página de configurações completa
|
||||
const staffRoles = new Set(["admin", "manager", "agent"])
|
||||
if (staffRoles.has(role)) {
|
||||
redirect("/settings/notifications")
|
||||
|
|
@ -32,9 +32,9 @@ export default async function PortalNotificationSettingsPage() {
|
|||
return (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-2xl font-semibold tracking-tight">Preferencias de notificacao</h1>
|
||||
<h1 className="text-2xl font-semibold tracking-tight">Preferências de notificação</h1>
|
||||
<p className="text-muted-foreground">
|
||||
Configure quais notificacoes por e-mail deseja receber sobre seus chamados.
|
||||
Configure quais notificações por e-mail deseja receber sobre seus chamados.
|
||||
</p>
|
||||
</div>
|
||||
<NotificationPreferencesForm isPortal />
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export default function RatePage() {
|
|||
const [comment, setComment] = useState("")
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
// Se ja avaliou, mostra mensagem
|
||||
// Se já avaliou, mostra mensagem
|
||||
if (alreadyRated && existingRating) {
|
||||
return (
|
||||
<div className="min-h-screen bg-background flex items-center justify-center p-4">
|
||||
|
|
@ -37,9 +37,9 @@ export default function RatePage() {
|
|||
<div className="flex justify-center mb-4">
|
||||
<CheckCircle className="h-16 w-16 text-emerald-500" />
|
||||
</div>
|
||||
<CardTitle>Chamado ja avaliado</CardTitle>
|
||||
<CardTitle>Chamado já avaliado</CardTitle>
|
||||
<CardDescription>
|
||||
Voce ja avaliou este chamado anteriormente.
|
||||
Você já avaliou este chamado anteriormente.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="text-center">
|
||||
|
|
@ -54,7 +54,7 @@ export default function RatePage() {
|
|||
))}
|
||||
</div>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
Sua avaliacao: {existingRating} estrela{existingRating > 1 ? "s" : ""}
|
||||
Sua avaliação: {existingRating} estrela{existingRating > 1 ? "s" : ""}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
|
@ -62,7 +62,7 @@ export default function RatePage() {
|
|||
)
|
||||
}
|
||||
|
||||
// Se acabou de avaliar, mostra formulario para comentario
|
||||
// Se acabou de avaliar, mostra formulário para comentário
|
||||
if (submitted && rating > 0) {
|
||||
return (
|
||||
<div className="min-h-screen bg-background flex items-center justify-center p-4">
|
||||
|
|
@ -71,9 +71,9 @@ export default function RatePage() {
|
|||
<div className="flex justify-center mb-4">
|
||||
<CheckCircle className="h-16 w-16 text-emerald-500" />
|
||||
</div>
|
||||
<CardTitle>Obrigado pela avaliacao!</CardTitle>
|
||||
<CardTitle>Obrigado pela avaliação!</CardTitle>
|
||||
<CardDescription>
|
||||
Sua opiniao e muito importante para nos.
|
||||
Sua opinião é muito importante para nós.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
|
|
@ -89,10 +89,10 @@ export default function RatePage() {
|
|||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="comment">Gostaria de deixar um comentario? (opcional)</Label>
|
||||
<Label htmlFor="comment">Gostaria de deixar um comentário? (opcional)</Label>
|
||||
<Textarea
|
||||
id="comment"
|
||||
placeholder="Conte-nos mais sobre sua experiencia..."
|
||||
placeholder="Conte-nos mais sobre sua experiência..."
|
||||
value={comment}
|
||||
onChange={(e) => setComment(e.target.value)}
|
||||
rows={4}
|
||||
|
|
@ -134,7 +134,7 @@ export default function RatePage() {
|
|||
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
throw new Error(data.error || "Erro ao enviar comentario")
|
||||
throw new Error(data.error || "Erro ao enviar comentário")
|
||||
}
|
||||
|
||||
window.close()
|
||||
|
|
@ -151,7 +151,7 @@ export default function RatePage() {
|
|||
Enviando...
|
||||
</>
|
||||
) : (
|
||||
"Enviar comentario"
|
||||
"Enviar comentário"
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -161,7 +161,7 @@ export default function RatePage() {
|
|||
)
|
||||
}
|
||||
|
||||
// Formulario de avaliacao
|
||||
// Formulário de avaliação
|
||||
return (
|
||||
<div className="min-h-screen bg-background flex items-center justify-center p-4">
|
||||
<Card className="w-full max-w-md">
|
||||
|
|
@ -174,7 +174,7 @@ export default function RatePage() {
|
|||
</div>
|
||||
<CardTitle>Como foi o atendimento?</CardTitle>
|
||||
<CardDescription>
|
||||
Sua avaliacao nos ajuda a melhorar nosso servico.
|
||||
Sua avaliação nos ajuda a melhorar nosso serviço.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
|
|
@ -206,12 +206,12 @@ export default function RatePage() {
|
|||
<span>Excelente</span>
|
||||
</div>
|
||||
|
||||
{/* Comentario */}
|
||||
{/* Comentário */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="comment">Comentario (opcional)</Label>
|
||||
<Label htmlFor="comment">Comentário (opcional)</Label>
|
||||
<Textarea
|
||||
id="comment"
|
||||
placeholder="Conte-nos mais sobre sua experiencia..."
|
||||
placeholder="Conte-nos mais sobre sua experiência..."
|
||||
value={comment}
|
||||
onChange={(e) => setComment(e.target.value)}
|
||||
rows={4}
|
||||
|
|
@ -225,7 +225,7 @@ export default function RatePage() {
|
|||
</div>
|
||||
)}
|
||||
|
||||
{/* Botao */}
|
||||
{/* Botão */}
|
||||
<Button
|
||||
className="w-full"
|
||||
size="lg"
|
||||
|
|
@ -243,7 +243,7 @@ export default function RatePage() {
|
|||
|
||||
if (!response.ok) {
|
||||
const data = await response.json()
|
||||
throw new Error(data.error || "Erro ao enviar avaliacao")
|
||||
throw new Error(data.error || "Erro ao enviar avaliação")
|
||||
}
|
||||
|
||||
setSubmitted(true)
|
||||
|
|
@ -260,7 +260,7 @@ export default function RatePage() {
|
|||
Enviando...
|
||||
</>
|
||||
) : (
|
||||
"Enviar avaliacao"
|
||||
"Enviar avaliação"
|
||||
)}
|
||||
</Button>
|
||||
</CardContent>
|
||||
|
|
|
|||
|
|
@ -7,15 +7,15 @@ import { NotificationPreferencesForm } from "@/components/settings/notification-
|
|||
import { requireAuthenticatedSession } from "@/lib/auth-server"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Preferencias de notificacao",
|
||||
description: "Configure quais notificacoes por e-mail deseja receber.",
|
||||
title: "Preferências de notificação",
|
||||
description: "Configure quais notificações por e-mail deseja receber.",
|
||||
}
|
||||
|
||||
export default async function NotificationSettingsPage() {
|
||||
const session = await requireAuthenticatedSession()
|
||||
const role = (session.user.role ?? "").toLowerCase()
|
||||
|
||||
// Apenas staff pode acessar esta pagina
|
||||
// Apenas staff pode acessar esta página
|
||||
const staffRoles = new Set(["admin", "manager", "agent"])
|
||||
if (!staffRoles.has(role)) {
|
||||
redirect("/portal/profile/notifications")
|
||||
|
|
@ -25,8 +25,8 @@ export default async function NotificationSettingsPage() {
|
|||
<AppShell
|
||||
header={
|
||||
<SiteHeader
|
||||
title="Preferencias de notificacao"
|
||||
lead="Configure como e quando deseja receber notificacoes por e-mail"
|
||||
title="Preferências de notificação"
|
||||
lead="Configure como e quando deseja receber notificações por e-mail"
|
||||
/>
|
||||
}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ export default function TicketViewPage() {
|
|||
try {
|
||||
window.location.href = ravenUrl
|
||||
} catch {
|
||||
// Protocolo nao suportado
|
||||
// Protocolo não suportado
|
||||
}
|
||||
|
||||
// Aguarda 2 segundos para ver se o protocolo foi aceito
|
||||
|
|
@ -123,7 +123,7 @@ export default function TicketViewPage() {
|
|||
document.body.removeChild(iframe)
|
||||
|
||||
if (!protocolHandled) {
|
||||
// Protocolo nao foi aceito, carrega o ticket no navegador
|
||||
// Protocolo não foi aceito, carrega o ticket no navegador
|
||||
setTryingRaven(false)
|
||||
loadTicket()
|
||||
}
|
||||
|
|
@ -153,10 +153,10 @@ export default function TicketViewPage() {
|
|||
<Loader2 className="h-12 w-12 animate-spin mx-auto mb-4 text-primary" />
|
||||
<h2 className="text-xl font-semibold mb-2">Abrindo no Raven...</h2>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
Se o aplicativo Raven estiver instalado, ele abrira automaticamente.
|
||||
Se o aplicativo Raven estiver instalado, ele abrirá automaticamente.
|
||||
</p>
|
||||
<p className="text-muted-foreground text-sm mt-2">
|
||||
Caso contrario, o chamado sera exibido aqui em instantes.
|
||||
Caso contrário, o chamado será exibido aqui em instantes.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
|
@ -243,15 +243,15 @@ export default function TicketViewPage() {
|
|||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
{/* Informacoes */}
|
||||
{/* Informações */}
|
||||
<div className="grid grid-cols-2 gap-4 text-sm">
|
||||
<div>
|
||||
<span className="text-muted-foreground">Solicitante</span>
|
||||
<p className="font-medium">{ticket.requester.name}</p>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-muted-foreground">Responsavel</span>
|
||||
<p className="font-medium">{ticket.assignee?.name ?? "Nao atribuido"}</p>
|
||||
<span className="text-muted-foreground">Responsável</span>
|
||||
<p className="font-medium">{ticket.assignee?.name ?? "Não atribuído"}</p>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-muted-foreground">Criado em</span>
|
||||
|
|
@ -274,17 +274,17 @@ export default function TicketViewPage() {
|
|||
{/* Resumo */}
|
||||
{ticket.summary && (
|
||||
<div>
|
||||
<h3 className="text-sm font-medium text-muted-foreground mb-2">Descricao</h3>
|
||||
<h3 className="text-sm font-medium text-muted-foreground mb-2">Descrição</h3>
|
||||
<p className="text-sm whitespace-pre-wrap">{ticket.summary}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Avaliacao */}
|
||||
{/* Avaliação */}
|
||||
{ticket.rating && (
|
||||
<div className="bg-muted/50 rounded-lg p-4">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<CheckCircle className="h-4 w-4 text-emerald-500" />
|
||||
<span className="text-sm font-medium">Avaliacao</span>
|
||||
<span className="text-sm font-medium">Avaliação</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1 mb-2">
|
||||
{[1, 2, 3, 4, 5].map((star) => (
|
||||
|
|
@ -302,12 +302,12 @@ export default function TicketViewPage() {
|
|||
</div>
|
||||
)}
|
||||
|
||||
{/* Comentarios */}
|
||||
{/* Comentários */}
|
||||
{ticket.comments.length > 0 && (
|
||||
<div>
|
||||
<h3 className="text-sm font-medium text-muted-foreground mb-4 flex items-center gap-2">
|
||||
<MessageSquare className="h-4 w-4" />
|
||||
Ultimas atualizacoes
|
||||
Últimas atualizações
|
||||
</h3>
|
||||
<div className="space-y-4">
|
||||
{ticket.comments.map((comment) => (
|
||||
|
|
|
|||
|
|
@ -36,26 +36,26 @@ interface NotificationPreferencesFormProps {
|
|||
isPortal?: boolean
|
||||
}
|
||||
|
||||
// Agrupamento de tipos de notificacao
|
||||
// Agrupamento de tipos de notificação
|
||||
const TYPE_GROUPS = {
|
||||
lifecycle: {
|
||||
label: "Ciclo de vida do chamado",
|
||||
description: "Notificacoes sobre abertura, resolucao e mudancas de status",
|
||||
description: "Notificações sobre abertura, resolução e mudanças de status",
|
||||
types: ["ticket_created", "ticket_assigned", "ticket_resolved", "ticket_reopened", "ticket_status_changed", "ticket_priority_changed"],
|
||||
},
|
||||
communication: {
|
||||
label: "Comunicacao",
|
||||
description: "Comentarios e respostas nos chamados",
|
||||
label: "Comunicação",
|
||||
description: "Comentários e respostas nos chamados",
|
||||
types: ["comment_public", "comment_response", "comment_mention"],
|
||||
},
|
||||
sla: {
|
||||
label: "SLA e alertas",
|
||||
description: "Alertas de prazo e metricas",
|
||||
description: "Alertas de prazo e métricas",
|
||||
types: ["sla_at_risk", "sla_breached", "sla_daily_digest"],
|
||||
},
|
||||
security: {
|
||||
label: "Seguranca",
|
||||
description: "Notificacoes de autenticacao e acesso",
|
||||
label: "Segurança",
|
||||
description: "Notificações de autenticação e acesso",
|
||||
types: ["security_password_reset", "security_email_verify", "security_email_change", "security_new_login", "security_invite"],
|
||||
},
|
||||
}
|
||||
|
|
@ -74,20 +74,20 @@ export function NotificationPreferencesForm({ isPortal = false }: NotificationPr
|
|||
try {
|
||||
const response = await fetch("/api/notifications/preferences")
|
||||
if (!response.ok) {
|
||||
throw new Error("Erro ao carregar preferencias")
|
||||
throw new Error("Erro ao carregar preferências")
|
||||
}
|
||||
const data = await response.json()
|
||||
setPreferences(data)
|
||||
|
||||
// Inicializa preferencias locais
|
||||
// Inicializa preferências locais
|
||||
const typePrefs: Record<string, boolean> = {}
|
||||
data.types.forEach((t: NotificationType) => {
|
||||
typePrefs[t.type] = t.enabled
|
||||
})
|
||||
setLocalTypePrefs(typePrefs)
|
||||
} catch (error) {
|
||||
console.error("Erro ao carregar preferencias:", error)
|
||||
toast.error("Nao foi possivel carregar suas preferencias")
|
||||
console.error("Erro ao carregar preferências:", error)
|
||||
toast.error("Não foi possível carregar suas preferências")
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
|
|
@ -112,13 +112,13 @@ export function NotificationPreferencesForm({ isPortal = false }: NotificationPr
|
|||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Erro ao salvar preferencias")
|
||||
throw new Error("Erro ao salvar preferências")
|
||||
}
|
||||
|
||||
toast.success("Preferencias salvas com sucesso")
|
||||
toast.success("Preferências salvas com sucesso")
|
||||
} catch (error) {
|
||||
console.error("Erro ao salvar preferencias:", error)
|
||||
toast.error("Nao foi possivel salvar suas preferencias")
|
||||
console.error("Erro ao salvar preferências:", error)
|
||||
toast.error("Não foi possível salvar suas preferências")
|
||||
} finally {
|
||||
setSaving(false)
|
||||
}
|
||||
|
|
@ -153,7 +153,7 @@ export function NotificationPreferencesForm({ isPortal = false }: NotificationPr
|
|||
<Card>
|
||||
<CardContent className="py-8">
|
||||
<p className="text-center text-muted-foreground">
|
||||
Nao foi possivel carregar suas preferencias de notificacao.
|
||||
Não foi possível carregar suas preferências de notificação.
|
||||
</p>
|
||||
<div className="flex justify-center mt-4">
|
||||
<Button onClick={loadPreferences}>Tentar novamente</Button>
|
||||
|
|
@ -163,7 +163,7 @@ export function NotificationPreferencesForm({ isPortal = false }: NotificationPr
|
|||
)
|
||||
}
|
||||
|
||||
// Filtra tipos visiveis para o usuario
|
||||
// Filtra tipos visíveis para o usuário
|
||||
const visibleTypes = preferences.types
|
||||
|
||||
// Agrupa tipos por categoria
|
||||
|
|
@ -177,15 +177,15 @@ export function NotificationPreferencesForm({ isPortal = false }: NotificationPr
|
|||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Configuracao global de e-mail */}
|
||||
{/* Configuração global de e-mail */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Mail className="h-5 w-5" />
|
||||
Notificacoes por e-mail
|
||||
Notificações por e-mail
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Controle se deseja receber notificacoes por e-mail.
|
||||
Controle se deseja receber notificações por e-mail.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
|
|
@ -194,8 +194,8 @@ export function NotificationPreferencesForm({ isPortal = false }: NotificationPr
|
|||
<Label className="text-base">Receber e-mails</Label>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{preferences.emailEnabled
|
||||
? "Voce recebera notificacoes por e-mail conforme suas preferencias"
|
||||
: "Todas as notificacoes por e-mail estao desativadas"}
|
||||
? "Você receberá notificações por e-mail conforme suas preferências"
|
||||
: "Todas as notificações por e-mail estão desativadas"}
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
|
|
@ -208,14 +208,14 @@ export function NotificationPreferencesForm({ isPortal = false }: NotificationPr
|
|||
<>
|
||||
<Separator />
|
||||
|
||||
{/* Horario de silencio - apenas staff */}
|
||||
{/* Horário de silêncio - apenas staff */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Clock className="h-4 w-4 text-muted-foreground" />
|
||||
<Label className="text-base">Horario de silencio</Label>
|
||||
<Label className="text-base">Horário de silêncio</Label>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Durante este periodo, notificacoes nao urgentes serao adiadas.
|
||||
Durante este período, notificações não urgentes serão adiadas.
|
||||
</p>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-2">
|
||||
|
|
@ -229,7 +229,7 @@ export function NotificationPreferencesForm({ isPortal = false }: NotificationPr
|
|||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Label htmlFor="quietEnd" className="text-sm">as</Label>
|
||||
<Label htmlFor="quietEnd" className="text-sm">às</Label>
|
||||
<Input
|
||||
id="quietEnd"
|
||||
type="time"
|
||||
|
|
@ -252,11 +252,11 @@ export function NotificationPreferencesForm({ isPortal = false }: NotificationPr
|
|||
|
||||
<Separator />
|
||||
|
||||
{/* Frequencia de resumo - apenas staff */}
|
||||
{/* Frequência de resumo - apenas staff */}
|
||||
<div className="space-y-4">
|
||||
<Label className="text-base">Frequencia de resumo</Label>
|
||||
<Label className="text-base">Frequência de resumo</Label>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Como voce prefere receber as notificacoes nao urgentes.
|
||||
Como você prefere receber as notificações não urgentes.
|
||||
</p>
|
||||
<Select
|
||||
value={preferences.digestFrequency}
|
||||
|
|
@ -267,7 +267,7 @@ export function NotificationPreferencesForm({ isPortal = false }: NotificationPr
|
|||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="immediate">Imediato</SelectItem>
|
||||
<SelectItem value="daily">Resumo diario</SelectItem>
|
||||
<SelectItem value="daily">Resumo diário</SelectItem>
|
||||
<SelectItem value="weekly">Resumo semanal</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
|
@ -277,19 +277,19 @@ export function NotificationPreferencesForm({ isPortal = false }: NotificationPr
|
|||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Tipos de notificacao */}
|
||||
{/* Tipos de notificação */}
|
||||
{preferences.emailEnabled && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Bell className="h-5 w-5" />
|
||||
Tipos de notificacao
|
||||
Tipos de notificação
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Escolha quais tipos de notificacao deseja receber.
|
||||
Escolha quais tipos de notificação deseja receber.
|
||||
{!preferences.isStaff && (
|
||||
<span className="block mt-1 text-amber-600">
|
||||
Algumas notificacoes sao obrigatorias e nao podem ser desativadas.
|
||||
Algumas notificações são obrigatórias e não podem ser desativadas.
|
||||
</span>
|
||||
)}
|
||||
</CardDescription>
|
||||
|
|
@ -323,7 +323,7 @@ export function NotificationPreferencesForm({ isPortal = false }: NotificationPr
|
|||
</Label>
|
||||
{notifType.required && (
|
||||
<Badge variant="secondary" className="ml-2 text-xs">
|
||||
Obrigatorio
|
||||
Obrigatório
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -343,7 +343,7 @@ export function NotificationPreferencesForm({ isPortal = false }: NotificationPr
|
|||
</Card>
|
||||
)}
|
||||
|
||||
{/* Botao de salvar */}
|
||||
{/* Botão de salvar */}
|
||||
<div className="flex justify-end">
|
||||
<Button onClick={savePreferences} disabled={saving}>
|
||||
{saving ? (
|
||||
|
|
@ -352,7 +352,7 @@ export function NotificationPreferencesForm({ isPortal = false }: NotificationPr
|
|||
Salvando...
|
||||
</>
|
||||
) : (
|
||||
"Salvar preferencias"
|
||||
"Salvar preferências"
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue