Frontend: - Implementar máscara de entrada de telefone para números BR ((XX) XXXXX-XXXX). - Atualizar formulário de cadastro para enviar dados completos do perfil do candidato (endereço, formação, habilidades, etc.). - Corrigir problemas de idioma misto na página de Detalhes da Vaga e adicionar traduções faltantes. Backend: - Atualizar modelo de Usuário, Entidade e DTOs para incluir campos de perfil (Data de Nascimento, Endereço, Formação, etc.). - Atualizar UserRepository para persistir e recuperar os dados estendidos do usuário no PostgreSQL. - Atualizar RegisterCandidateUseCase para mapear campos de entrada para a entidade Usuário.
193 lines
4.9 KiB
TypeScript
193 lines
4.9 KiB
TypeScript
"use client";
|
|
|
|
import React, { createContext, useContext, useState, useCallback, useEffect } from "react";
|
|
import { toast } from "sonner";
|
|
import type { Notification } from "@/lib/types";
|
|
import { mockNotifications, mockCompanyNotifications } from "@/lib/mock-data";
|
|
import { getCurrentUser } from "@/lib/auth";
|
|
|
|
interface NotificationContextType {
|
|
notifications: Notification[];
|
|
addNotification: (
|
|
notification: Omit<Notification, "id" | "createdAt" | "read">
|
|
) => void;
|
|
markAsRead: (id: string) => void;
|
|
markAllAsRead: () => void;
|
|
removeNotification: (id: string) => void;
|
|
clearAllNotifications: () => void;
|
|
unreadCount: number;
|
|
}
|
|
|
|
const NotificationContext = createContext<NotificationContextType | undefined>(
|
|
undefined
|
|
);
|
|
|
|
export function NotificationProvider({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode;
|
|
}) {
|
|
const [notifications, setNotifications] = useState<Notification[]>([]);
|
|
|
|
useEffect(() => {
|
|
const user = getCurrentUser();
|
|
if (user?.role === "company") {
|
|
setNotifications(mockCompanyNotifications);
|
|
} else {
|
|
setNotifications(mockNotifications);
|
|
}
|
|
}, []);
|
|
|
|
const addNotification = useCallback(
|
|
(notification: Omit<Notification, "id" | "createdAt" | "read">) => {
|
|
const newNotification: Notification = {
|
|
...notification,
|
|
id: Date.now().toString(),
|
|
createdAt: new Date().toISOString(),
|
|
read: false,
|
|
};
|
|
|
|
setNotifications((prev) => [newNotification, ...prev]);
|
|
|
|
// Show toast notification
|
|
switch (notification.type) {
|
|
case "success":
|
|
toast.success(notification.title, {
|
|
description: notification.message,
|
|
});
|
|
break;
|
|
case "error":
|
|
toast.error(notification.title, {
|
|
description: notification.message,
|
|
});
|
|
break;
|
|
case "warning":
|
|
toast.warning(notification.title, {
|
|
description: notification.message,
|
|
});
|
|
break;
|
|
default:
|
|
toast.info(notification.title, {
|
|
description: notification.message,
|
|
});
|
|
break;
|
|
}
|
|
},
|
|
[]
|
|
);
|
|
|
|
const markAsRead = useCallback((id: string) => {
|
|
setNotifications((prev) =>
|
|
prev.map((notification) =>
|
|
notification.id === id ? { ...notification, read: true } : notification
|
|
)
|
|
);
|
|
}, []);
|
|
|
|
const markAllAsRead = useCallback(() => {
|
|
setNotifications((prev) =>
|
|
prev.map((notification) => ({ ...notification, read: true }))
|
|
);
|
|
}, []);
|
|
|
|
const removeNotification = useCallback((id: string) => {
|
|
setNotifications((prev) =>
|
|
prev.filter((notification) => notification.id !== id)
|
|
);
|
|
}, []);
|
|
|
|
const clearAllNotifications = useCallback(() => {
|
|
setNotifications([]);
|
|
}, []);
|
|
|
|
const unreadCount = notifications.filter((n) => !n.read).length;
|
|
|
|
return (
|
|
<NotificationContext.Provider
|
|
value={{
|
|
notifications,
|
|
addNotification,
|
|
markAsRead,
|
|
markAllAsRead,
|
|
removeNotification,
|
|
clearAllNotifications,
|
|
unreadCount,
|
|
}}
|
|
>
|
|
{children}
|
|
</NotificationContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useNotifications() {
|
|
const context = useContext(NotificationContext);
|
|
if (context === undefined) {
|
|
throw new Error(
|
|
"useNotifications must be used within a NotificationProvider"
|
|
);
|
|
}
|
|
return context;
|
|
}
|
|
|
|
// Hook personalizado para facilitar o uso
|
|
export function useNotify() {
|
|
const { addNotification } = useNotifications();
|
|
|
|
return React.useMemo(() => ({
|
|
success: (
|
|
title: string,
|
|
message: string,
|
|
options?: { actionUrl?: string; actionLabel?: string; userId?: string }
|
|
) =>
|
|
addNotification({
|
|
title,
|
|
message,
|
|
type: "success",
|
|
userId: options?.userId || "current",
|
|
actionUrl: options?.actionUrl,
|
|
actionLabel: options?.actionLabel,
|
|
}),
|
|
|
|
error: (
|
|
title: string,
|
|
message: string,
|
|
options?: { actionUrl?: string; actionLabel?: string; userId?: string }
|
|
) =>
|
|
addNotification({
|
|
title,
|
|
message,
|
|
type: "error",
|
|
userId: options?.userId || "current",
|
|
actionUrl: options?.actionUrl,
|
|
actionLabel: options?.actionLabel,
|
|
}),
|
|
|
|
warning: (
|
|
title: string,
|
|
message: string,
|
|
options?: { actionUrl?: string; actionLabel?: string; userId?: string }
|
|
) =>
|
|
addNotification({
|
|
title,
|
|
message,
|
|
type: "warning",
|
|
userId: options?.userId || "current",
|
|
actionUrl: options?.actionUrl,
|
|
actionLabel: options?.actionLabel,
|
|
}),
|
|
|
|
info: (
|
|
title: string,
|
|
message: string,
|
|
options?: { actionUrl?: string; actionLabel?: string; userId?: string }
|
|
) =>
|
|
addNotification({
|
|
title,
|
|
message,
|
|
type: "info",
|
|
userId: options?.userId || "current",
|
|
actionUrl: options?.actionUrl,
|
|
actionLabel: options?.actionLabel,
|
|
}),
|
|
}), [addNotification]);
|
|
}
|