From fb7dc476484a9fa24a9bff4976a5cb54be0cd2d9 Mon Sep 17 00:00:00 2001 From: Ruan Bueno Date: Mon, 29 Jun 2026 14:31:37 -0300 Subject: [PATCH] feat: adicionar novo video --- src/app/(authenticated)/dashboard/page.tsx | 445 +++++++++++-------- src/components/dashboard/videos-carousel.tsx | 125 +++--- 2 files changed, 328 insertions(+), 242 deletions(-) diff --git a/src/app/(authenticated)/dashboard/page.tsx b/src/app/(authenticated)/dashboard/page.tsx index 9b0258f..cf7defd 100644 --- a/src/app/(authenticated)/dashboard/page.tsx +++ b/src/app/(authenticated)/dashboard/page.tsx @@ -1,168 +1,220 @@ -"use client" +"use client"; -import { MainCarousel } from "@/components/dashboard/main-carousel" -import { BirthdaysCarousel } from "@/components/dashboard/birthdays-carousel" -import { api } from "@/trpc/react" -import { cn } from "@/lib/utils" -import { LinkIcon, LucideGraduationCap, Coffee, Sparkles, LucideMegaphone } from "lucide-react" -import { motion } from "framer-motion" -import { VideosCarousel } from "@/components/dashboard/videos-carousel" -import Link from "next/link" -import { NewsDisplay } from "@/components/dashboard/news-displ" -import { routeItems, type RouteItem } from "@/const/routes" -import { canViewHallEntrada } from "@/lib/access-control" -import { FaInstagram, FaFacebook, FaYoutube } from "react-icons/fa6" -import Image from "next/image" -import { DashboardShell } from "@/components/ui/dashboard-shell" +import { MainCarousel } from "@/components/dashboard/main-carousel"; +import { BirthdaysCarousel } from "@/components/dashboard/birthdays-carousel"; +import { api } from "@/trpc/react"; +import { cn } from "@/lib/utils"; +import { + LinkIcon, + LucideGraduationCap, + Coffee, + Sparkles, + LucideMegaphone, +} from "lucide-react"; +import { motion } from "framer-motion"; +import { VideosCarousel } from "@/components/dashboard/videos-carousel"; +import Link from "next/link"; +import { NewsDisplay } from "@/components/dashboard/news-displ"; +import { routeItems, type RouteItem } from "@/const/routes"; +import { canViewHallEntrada } from "@/lib/access-control"; +import { FaInstagram, FaFacebook, FaYoutube } from "react-icons/fa6"; +import Image from "next/image"; +import { DashboardShell } from "@/components/ui/dashboard-shell"; -import { SuggestionsWrapper } from "./suggestions-wrapper" -import { CompleteProfileModal } from "@/components/ui/complete-profile-modal" -import { WelcomeCard } from "@/components/dashboard/welcome-card" -import { EmotionRulerWrapper } from "@/components/emotion-ruler/emotion-ruler-wrapper" -import { useState, useEffect, useMemo } from "react" +import { SuggestionsWrapper } from "./suggestions-wrapper"; +import { CompleteProfileModal } from "@/components/ui/complete-profile-modal"; +import { WelcomeCard } from "@/components/dashboard/welcome-card"; +import { EmotionRulerWrapper } from "@/components/emotion-ruler/emotion-ruler-wrapper"; +import { useState, useEffect, useMemo } from "react"; // Variantes de animação para o footer const fadeInUp = { hidden: { opacity: 0, y: 20 }, - visible: { opacity: 1, y: 0 } -} + visible: { opacity: 1, y: 0 }, +}; const transitionDefault = { duration: 0.5, - ease: [0.4, 0, 0.2, 1] as const -} + ease: [0.4, 0, 0.2, 1] as const, +}; export default function DashboardPage() { - const [showProfileModal, setShowProfileModal] = useState(false) + const [showProfileModal, setShowProfileModal] = useState(false); // Buscar dados usando client-side tRPC - const { data: birthdays } = api.birthday.listCurrentMonth.useQuery() - const { data: user, refetch: refetchUser } = api.user.me.useQuery() + const { data: birthdays } = api.birthday.listCurrentMonth.useQuery(); + const { data: user, refetch: refetchUser } = api.user.me.useQuery(); // Tipagem para os dados do usuário // Removido: userRole não é mais necessário com novo sistema - const userEnterprise = user?.enterprise ?? null - const userSetor = user?.setor ?? null - const userMatricula = user?.matricula ?? null - const userFilialId = user?.filialId ?? null - const isFilialEnterprise = userEnterprise === "Box_Filial" || userEnterprise === "Cristallux_Filial" - const isTotem = user?.role_config?.isTotem === true + const userEnterprise = user?.enterprise ?? null; + const userSetor = user?.setor ?? null; + const userMatricula = user?.matricula ?? null; + const userFilialId = user?.filialId ?? null; + const isFilialEnterprise = + userEnterprise === "Box_Filial" || userEnterprise === "Cristallux_Filial"; + const isTotem = user?.role_config?.isTotem === true; // Verificar se os campos obrigatórios estão preenchidos (filial apenas para empresas do tipo filial) useEffect(() => { - if (user && (!userMatricula?.trim() || !userEnterprise || !userSetor || (isFilialEnterprise && !userFilialId))) { - setShowProfileModal(true) + if ( + user && + (!userMatricula?.trim() || + !userEnterprise || + !userSetor || + (isFilialEnterprise && !userFilialId)) + ) { + setShowProfileModal(true); } - }, [user, userMatricula, userEnterprise, userSetor, userFilialId, isFilialEnterprise]) + }, [ + user, + userMatricula, + userEnterprise, + userSetor, + userFilialId, + isFilialEnterprise, + ]); const todayBirthdays = useMemo(() => { if (!birthdays) { - return [] + return []; } // Ajustar para usar o dia anterior (dia 09 ao invés do dia 10) - const today = new Date() - today.setDate(today.getDate() - 1) // SPE - FAMOSA GAMBIARRA - const currentDay = today.getDate() - const currentMonth = today.getMonth() + const today = new Date(); + today.setDate(today.getDate() - 1); // SPE - FAMOSA GAMBIARRA + const currentDay = today.getDate(); + const currentMonth = today.getMonth(); return birthdays.filter((birthday) => { - const birthdayDate = new Date(birthday.data) + const birthdayDate = new Date(birthday.data); return ( birthdayDate.getDate() === currentDay && birthdayDate.getMonth() === currentMonth - ) - }) - }, [birthdays]) + ); + }); + }, [birthdays]); - const hasTodayBirthdays = todayBirthdays.length > 0 + const hasTodayBirthdays = todayBirthdays.length > 0; const announcementShortcuts = useMemo(() => { - const routes = routeItems(user?.role_config, false, user?.novidades === true) - const group = routes.find((m) => m.title === "Anúncios") + const routes = routeItems( + user?.role_config, + false, + user?.novidades === true, + ); + const group = routes.find((m) => m.title === "Anúncios"); const withHref = - group?.children?.filter((c): c is RouteItem & { href: string } => Boolean(c.href)) ?? [] + group?.children?.filter((c): c is RouteItem & { href: string } => + Boolean(c.href), + ) ?? []; return withHref.filter((c) => { if (c.href === "/forms/hall-entrada") { - return canViewHallEntrada(user?.role_config ?? null) + return canViewHallEntrada(user?.role_config ?? null); } - return true - }) - }, [user?.role_config, user?.novidades]) + return true; + }); + }, [user?.role_config, user?.novidades]); const posts: { - imageRef: string, - title: string, + imageRef: string; + title: string; }[] = [ - { - imageRef: '/banners/Banners-intranet-1.png', - title: 'Banners-intranet-1', - }, - { - imageRef: '/banners/Banners-intranet-2.png', - title: 'Banners-intranet-2', - }, - { - imageRef: '/banners/Banners-intranet-4.png', - title: 'Banners-intranet-4', - }, - { - imageRef: '/banners/Banners-intranet-6.jpg', - title: 'Banners-intranet-6', - }, - ] + { + imageRef: "/banners/Banners-intranet-1.png", + title: "Banners-intranet-1", + }, + { + imageRef: "/banners/Banners-intranet-2.png", + title: "Banners-intranet-2", + }, + { + imageRef: "/banners/Banners-intranet-4.png", + title: "Banners-intranet-4", + }, + { + imageRef: "/banners/Banners-intranet-6.jpg", + title: "Banners-intranet-6", + }, + ]; const videos: { - imageRef: string, - title: string, + imageRef: string; + title: string; }[] = [ - { - imageRef: 'https://www.youtube.com/embed/AIlQ-EM35UQ?si=RomGdNhQLn6CuzCw', - title: 'Institucional Cristallux', - }, - ] + { + imageRef: "https://www.youtube.com/embed/AIlQ-EM35UQ?si=RomGdNhQLn6CuzCw", + title: "Institucional Cristallux", + }, + { + imageRef: "https://www.youtube.com/embed/nW-_4kfXE4U?si=tFAOWTij0oSkdcCm", + title: "Apresentação Box Distribuidor", + }, + { + imageRef: "https://www.youtube.com/embed/iSdz3gxUpAI", + title: "Valores Grupo RHenz", + }, + ]; return (
{/* Modal da Régua de Emoções */} {/* Card de Boas-vindas para novos colaboradores */} -
+
{/* Seção Principal - Banners e Aniversários */} -
- { - posts.length > 0 && - - } - { - hasTodayBirthdays && ( - ({ +
+ {posts.length > 0 && ( + + )} + {hasTodayBirthdays && ( + ({ imageRef: b.imageUrl ?? b.user?.imageUrl ?? "", - title: b.name - }))} /> - ) - } + title: b.name, + }))} + /> + )}
-
+
{/* Funcionalidades Mobile */}
-

+

Funcionalidades

-
- { - routeItems(user?.role_config, false, user?.novidades === true).map((m, i) => m.title !== "Dashboard" && m.href && ( -
- - - {m.title} - -
- )) - } +
+ {routeItems(user?.role_config, false, user?.novidades === true).map( + (m, i) => + m.title !== "Dashboard" && + m.href && ( +
+ + + + {m.title} + + +
+ ), + )}
{announcementShortcuts.length > 0 ? (
@@ -175,10 +227,12 @@ export default function DashboardPage() { - {item.title} + + {item.title} + ))}
@@ -187,24 +241,24 @@ export default function DashboardPage() {
{/* Links Úteis, Universidade Corporativa e Ideias */} -
+
{/* Links Úteis — apenas sites */} -
-
+
+
Links Úteis
@@ -212,14 +266,16 @@ export default function DashboardPage() { src="/LOGO BOX.png" height={24} width={24} - className="rounded-sm mr-2 md:mr-3 flex-shrink-0 size-5 md:size-6" + className="mr-2 size-5 flex-shrink-0 rounded-sm md:mr-3 md:size-6" alt="Site Box" /> - Site Box + + Site Box + @@ -227,14 +283,16 @@ export default function DashboardPage() { src="/icon_cristal.svg" height={24} width={24} - className="rounded-sm mr-2 md:mr-3 flex-shrink-0 size-5 md:size-6" + className="mr-2 size-5 flex-shrink-0 rounded-sm md:mr-3 md:size-6" alt="Cristallux" /> - Cristallux + + Cristallux + @@ -242,25 +300,27 @@ export default function DashboardPage() { src="/central-funcionario.ico" height={24} width={24} - className="rounded-sm mr-2 md:mr-3 flex-shrink-0 size-5 md:size-6" + className="mr-2 size-5 flex-shrink-0 rounded-sm md:mr-3 md:size-6" alt="Central do Colaborador" /> - Central do Colaborador + + Central do Colaborador +
{/* Universidade Corporativa */} -
-
- +
+
+ Universidade Corporativa
@@ -268,14 +328,14 @@ export default function DashboardPage() { src="/LOGO BOX.png" height={24} width={24} - className="rounded-sm mr-2 md:mr-3 flex-shrink-0 size-5 md:size-6" + className="mr-2 size-5 flex-shrink-0 rounded-sm md:mr-3 md:size-6" alt="Box Uni" /> - Box Uni + Box Uni @@ -283,14 +343,18 @@ export default function DashboardPage() { src="/icon_cristal.svg" height={24} width={24} - className="rounded-sm mr-2 md:mr-3 flex-shrink-0 size-5 md:size-6" + className="mr-2 size-5 flex-shrink-0 rounded-sm md:mr-3 md:size-6" alt="CristalUni" /> - CristalUni + + CristalUni + @@ -298,18 +362,18 @@ export default function DashboardPage() { src="/umentor.jpg" height={24} width={24} - className="rounded-sm mr-2 md:mr-3 flex-shrink-0 size-5 md:size-6" + className="mr-2 size-5 flex-shrink-0 rounded-sm md:mr-3 md:size-6" alt="Umentor" /> - Umentor + Umentor
{/* Card de Ideias - Não exibir para usuários Totem */} {!isTotem && ( -
-

+
+

Ideias

@@ -317,13 +381,14 @@ export default function DashboardPage() { )}

-
- {/* Seção de Conteúdo - Video e Clima */} - { - videos.length > 0 && ( - - ) - } +
+ {videos.length > 0 && ( + + )}
@@ -332,47 +397,65 @@ export default function DashboardPage() {
{/* Footer com Redes Sociais */} -
-
-
+
+
+
{/* Redes Sociais */}
-

+

Redes Sociais

- +
- + @box.distribuidor | - + @cristalluxled
- +
- + @fiosecia.boxdistribuidor | - + @cristalluxled
- +
- + @boxdistribuidor | - + @cristalluxled
@@ -381,15 +464,15 @@ export default function DashboardPage() {
{/* Copyright e desenvolvedor */} -
+
-

+

©️ {new Date().getFullYear()} Elo | Intranet

@@ -397,11 +480,13 @@ export default function DashboardPage() { - Feito com + + Feito com + - por + por EzLab - +
@@ -433,18 +518,22 @@ export default function DashboardPage() { {/* Modal para completar perfil */} { - void refetchUser() + void refetchUser(); }} onClose={() => setShowProfileModal(false)} />
- ) -} \ No newline at end of file + ); +} diff --git a/src/components/dashboard/videos-carousel.tsx b/src/components/dashboard/videos-carousel.tsx index 60cc245..c3812d5 100644 --- a/src/components/dashboard/videos-carousel.tsx +++ b/src/components/dashboard/videos-carousel.tsx @@ -1,82 +1,70 @@ -"use client" +"use client"; -import { Carousel, CarouselContent, CarouselItem, type CarouselApi } from "@/components/ui/carousel" -import { cn } from "@/lib/utils" -import { useEffect, useState } from "react" -import { WeatherWidget } from "@/components/dashboard/weather-widget" -import type { Enterprise } from "@/types/enterprise" +import { + Carousel, + CarouselContent, + CarouselItem, + type CarouselApi, +} from "@/components/ui/carousel"; +import { cn } from "@/lib/utils"; +import { useEffect, useState } from "react"; +import { WeatherWidget } from "@/components/dashboard/weather-widget"; +import type { Enterprise } from "@/types/enterprise"; interface MainCarouselProps { itens: { - imageRef: string - title: string - }[], - className?: string - enterprise?: Enterprise | null + imageRef: string; + title: string; + }[]; + className?: string; + enterprise?: Enterprise | null; } -export function VideosCarousel({ itens, className, enterprise }: MainCarouselProps) { - const [carouselApi, setCarouselApi] = useState() - const [current, setCurrent] = useState(0) - const [count, setCount] = useState(0) +export function VideosCarousel({ + itens, + className, + enterprise, +}: MainCarouselProps) { + const [carouselApi, setCarouselApi] = useState(); + const [current, setCurrent] = useState(0); + const [count, setCount] = useState(0); useEffect(() => { if (!carouselApi) { - return + return; } - setCount(carouselApi.scrollSnapList().length) - setCurrent(carouselApi.selectedScrollSnap()) + setCount(carouselApi.scrollSnapList().length); + setCurrent(carouselApi.selectedScrollSnap()); carouselApi.on("select", () => { - setCurrent(carouselApi.selectedScrollSnap()) - }) - }, [carouselApi]) + setCurrent(carouselApi.selectedScrollSnap()); + }); + }, [carouselApi]); return (
{/* Grid estático no desktop - 3 colunas */} -
+
{/* Primeira coluna - Vídeos */} {itens.map((item, index) => ( -
-
+
+
))} - - {/* Segunda coluna - Vídeo Box */} -
-
- -
-
- - {/* Terceira coluna - WeatherWidget */} -
-
- -
-
{/* Carrossel no mobile */} -
+
- + {itens.map((item, index) => ( - -
+ +
))} - -
+ +
- -
+ +
@@ -126,12 +124,12 @@ export function VideosCarousel({ itens, className, enterprise }: MainCarouselPro {/* Indicators - Apenas no mobile */} {count > 0 && ( -
-
+
+
{Array.from({ length: count }).map((_, index) => (
- ) + ); } -