From 6100c998be35e5d30ef1a863714af90dc6599f54 Mon Sep 17 00:00:00 2001 From: Jose Selesan Date: Wed, 16 Sep 2026 17:35:24 -0300 Subject: [PATCH] feat: add brand assets, design tokens and light/dark theme - Use real logo/isotype SVGs across app and emails - Token-based color system aligned with landing (brand scale + semantic tokens) - ThemeProvider (light/dark/system) with header toggle and settings card - Embed logo in transactional emails; centralize email colors --- .../src/assets/logotipo-y-organica.png | Bin 0 -> 29085 bytes apps/backend/src/lib/email.ts | 40 +++++- apps/web/index.html | 21 ++- apps/web/public/apple-touch-icon.png | Bin 0 -> 16038 bytes apps/web/public/favicon.svg | 12 ++ .../brand/isotipo-y-organica-oscuro.svg | 6 + .../src/assets/brand/isotipo-y-organica.svg | 6 + .../brand/logotipo-y-organica-oscuro.svg | 7 + .../src/assets/brand/logotipo-y-organica.svg | 7 + apps/web/src/components/auth/AuthShell.tsx | 9 +- apps/web/src/components/brand/Logo.tsx | 34 +++-- apps/web/src/components/brand/LogoIcon.tsx | 22 ++- apps/web/src/components/layout/BottomNav.tsx | 4 +- apps/web/src/components/layout/Header.tsx | 29 +++- apps/web/src/components/layout/Sidebar.tsx | 11 +- apps/web/src/components/layout/UserMenu.tsx | 12 +- .../onboarding/ConfirmationStep.tsx | 2 +- .../components/onboarding/FirstGroupStep.tsx | 6 +- .../src/components/onboarding/PaymentStep.tsx | 6 +- .../web/src/components/onboarding/Stepper.tsx | 2 +- .../src/components/onboarding/WelcomeStep.tsx | 2 +- apps/web/src/components/ui/avatar.tsx | 2 +- apps/web/src/components/ui/button.tsx | 4 +- apps/web/src/components/ui/input.tsx | 2 +- apps/web/src/context/ThemeProvider.tsx | 68 +++++++++ apps/web/src/index.css | 133 ++++++++++++++---- apps/web/src/main.tsx | 9 +- apps/web/src/routes/auth/verify-email.tsx | 2 +- apps/web/src/routes/groups.tsx | 4 +- apps/web/src/routes/onboarding.tsx | 7 +- apps/web/src/routes/organizations.tsx | 6 +- apps/web/src/routes/profile.tsx | 2 +- apps/web/src/routes/security.tsx | 6 +- apps/web/src/routes/settings.tsx | 67 ++++++++- 34 files changed, 435 insertions(+), 115 deletions(-) create mode 100644 apps/backend/src/assets/logotipo-y-organica.png create mode 100644 apps/web/public/apple-touch-icon.png create mode 100644 apps/web/public/favicon.svg create mode 100644 apps/web/src/assets/brand/isotipo-y-organica-oscuro.svg create mode 100644 apps/web/src/assets/brand/isotipo-y-organica.svg create mode 100644 apps/web/src/assets/brand/logotipo-y-organica-oscuro.svg create mode 100644 apps/web/src/assets/brand/logotipo-y-organica.svg create mode 100644 apps/web/src/context/ThemeProvider.tsx diff --git a/apps/backend/src/assets/logotipo-y-organica.png b/apps/backend/src/assets/logotipo-y-organica.png new file mode 100644 index 0000000000000000000000000000000000000000..4179eaddf6285cd41c41adaffc01d37aa7c86870 GIT binary patch literal 29085 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 BN6`QP literal 0 HcmV?d00001 diff --git a/apps/backend/src/lib/email.ts b/apps/backend/src/lib/email.ts index e2269e9..83abbcf 100644 --- a/apps/backend/src/lib/email.ts +++ b/apps/backend/src/lib/email.ts @@ -1,9 +1,31 @@ +import { readFileSync } from 'node:fs' import nodemailer, { type Transporter } from 'nodemailer' type VerificationEmailData = { email: string; url: string; name?: string } type PasswordResetEmailData = { email: string; url: string; name?: string } type InvitationEmailData = { email: string; url: string; organizationName: string } +// Colores de marca (mismo sistema que la web: index.css de apps/web). +const BRAND_600 = '#2544ea' +const TEXT_STRONG = '#0f172a' +const TEXT_MUTED = '#475569' +const ON_ACCENT = '#ffffff' +const LINK_BG = BRAND_600 + +// Logotipo embebido como data URI para que los mails no dependan de hosting. +function loadLogoTypoDataUri(): string { + try { + const base64 = readFileSync( + new URL('../assets/logotipo-y-organica.png', import.meta.url), + ).toString('base64') + return `data:image/png;base64,${base64}` + } catch { + return '' + } +} + +const LOGO_DATA_URI = loadLogoTypoDataUri() + interface EmailProvider { sendVerificationEmail(data: VerificationEmailData): Promise sendPasswordResetEmail(data: PasswordResetEmailData): Promise @@ -30,11 +52,15 @@ class SMTPEmailProvider implements EmailProvider { } private layout(title: string, body: string) { + const header = LOGO_DATA_URI + ? `Gruperly` + : '

Gruperly

' + return ` -
-

Gruperly

-

${title}

-

${body}

+
+
${header}
+

${title}

+

${body}

` } @@ -49,7 +75,7 @@ class SMTPEmailProvider implements EmailProvider { } async sendVerificationEmail({ email, url, name }: VerificationEmailData) { - const link = `
Verificar email` + const link = `Verificar email` await this.send( email, 'Verifica tu email en Gruperly', @@ -61,7 +87,7 @@ class SMTPEmailProvider implements EmailProvider { } async sendPasswordResetEmail({ email, url, name }: PasswordResetEmailData) { - const link = `Restablecer contraseña` + const link = `Restablecer contraseña` await this.send( email, 'Restablece tu contraseña en Gruperly', @@ -73,7 +99,7 @@ class SMTPEmailProvider implements EmailProvider { } async sendOrganizationInvitation({ email, url, organizationName }: InvitationEmailData) { - const link = `Unirme a ${organizationName}` + const link = `Unirme a ${organizationName}` await this.send( email, `Te invitaron a ${organizationName} en Gruperly`, diff --git a/apps/web/index.html b/apps/web/index.html index 55e9213..1b6cde3 100644 --- a/apps/web/index.html +++ b/apps/web/index.html @@ -4,9 +4,28 @@ Gruperly + + + + + +
- + \ No newline at end of file diff --git a/apps/web/public/apple-touch-icon.png b/apps/web/public/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9817109702219a079a4869cae1bb36f5ef3160c6 GIT binary patch literal 16038 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 + Gruperly + + + + \ No newline at end of file diff --git a/apps/web/src/assets/brand/isotipo-y-organica-oscuro.svg b/apps/web/src/assets/brand/isotipo-y-organica-oscuro.svg new file mode 100644 index 0000000..1ac5bc2 --- /dev/null +++ b/apps/web/src/assets/brand/isotipo-y-organica-oscuro.svg @@ -0,0 +1,6 @@ + + Gruperly — isotipo y orgánica + Y orgánica con rama corta blanco azulado #EEF4FF y diagonal larga celeste #93B4FD, separadas, sobre fondo transparente. + + + \ No newline at end of file diff --git a/apps/web/src/assets/brand/isotipo-y-organica.svg b/apps/web/src/assets/brand/isotipo-y-organica.svg new file mode 100644 index 0000000..a7f9dcd --- /dev/null +++ b/apps/web/src/assets/brand/isotipo-y-organica.svg @@ -0,0 +1,6 @@ + + Gruperly — isotipo y orgánica + Y orgánica con rama corta azul noche #171D54 y diagonal larga celeste #93B4FD, separadas, sobre fondo transparente. + + + \ No newline at end of file diff --git a/apps/web/src/assets/brand/logotipo-y-organica-oscuro.svg b/apps/web/src/assets/brand/logotipo-y-organica-oscuro.svg new file mode 100644 index 0000000..2335bda --- /dev/null +++ b/apps/web/src/assets/brand/logotipo-y-organica-oscuro.svg @@ -0,0 +1,7 @@ + +Gruperly — y orgánica bicolor +Rama corta azul noche y diagonal larga celeste, separadas, con curvas suaves y terminales redondeados. + + + + \ No newline at end of file diff --git a/apps/web/src/assets/brand/logotipo-y-organica.svg b/apps/web/src/assets/brand/logotipo-y-organica.svg new file mode 100644 index 0000000..5a4f989 --- /dev/null +++ b/apps/web/src/assets/brand/logotipo-y-organica.svg @@ -0,0 +1,7 @@ + +Gruperly — y orgánica bicolor +Rama corta azul noche y diagonal larga celeste, separadas, con curvas suaves y terminales redondeados. + + + + \ No newline at end of file diff --git a/apps/web/src/components/auth/AuthShell.tsx b/apps/web/src/components/auth/AuthShell.tsx index a0c0158..f080c85 100644 --- a/apps/web/src/components/auth/AuthShell.tsx +++ b/apps/web/src/components/auth/AuthShell.tsx @@ -1,5 +1,5 @@ import type { ReactNode } from 'react' -import { Logo, LogoIcon } from '../brand' +import { Logo } from '../brand' export type AuthShellProps = { title: string @@ -11,11 +11,10 @@ export function AuthShell({ title, subtitle, children }: AuthShellProps) { return (
-
- - +
+
-
+

{title}

{subtitle ?

{subtitle}

: null}
{children}
diff --git a/apps/web/src/components/brand/Logo.tsx b/apps/web/src/components/brand/Logo.tsx index 514b481..22e5512 100644 --- a/apps/web/src/components/brand/Logo.tsx +++ b/apps/web/src/components/brand/Logo.tsx @@ -1,23 +1,35 @@ -import { forwardRef, type HTMLAttributes } from 'react' +import { forwardRef, type SVGProps } from 'react' import { cn } from '../../lib/utils' -export type LogoProps = Omit, 'children'> & { - className?: string -} +export type LogoProps = SVGProps -export const Logo = forwardRef( +export const Logo = forwardRef( ({ className, ...props }, ref) => { return ( - - gruperl - y - + Gruperly + + + + ) }, ) -Logo.displayName = 'Logo' +Logo.displayName = 'Logo' \ No newline at end of file diff --git a/apps/web/src/components/brand/LogoIcon.tsx b/apps/web/src/components/brand/LogoIcon.tsx index 2250e30..e3993aa 100644 --- a/apps/web/src/components/brand/LogoIcon.tsx +++ b/apps/web/src/components/brand/LogoIcon.tsx @@ -10,30 +10,24 @@ export const LogoIcon = forwardRef( return ( - Gruperly + - ) }, ) -LogoIcon.displayName = 'LogoIcon' +LogoIcon.displayName = 'LogoIcon' \ No newline at end of file diff --git a/apps/web/src/components/layout/BottomNav.tsx b/apps/web/src/components/layout/BottomNav.tsx index 5cd17a0..05adc0f 100644 --- a/apps/web/src/components/layout/BottomNav.tsx +++ b/apps/web/src/components/layout/BottomNav.tsx @@ -6,7 +6,7 @@ export function BottomNav() { const location = useLocation() return ( -