From c0bc27dbc5df300f3ed248d16f72b6be8e011ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Evandro=20Pican=C3=A7o?= <6420942+expectpin@users.noreply.github.com> Date: Thu, 4 Sep 2025 09:08:27 -0400 Subject: [PATCH 1/2] feat: add interactive RSVP confirmation form with WhatsApp integration --- src/app/app.css | 250 +++++++++++++++++++++- src/app/app.html | 101 ++++++++- src/app/app.ts | 99 ++++++++- src/environments/environment.interface.ts | 34 +++ src/environments/environment.prod.ts | 5 +- 5 files changed, 483 insertions(+), 6 deletions(-) create mode 100644 src/environments/environment.interface.ts diff --git a/src/app/app.css b/src/app/app.css index 2469639..73b4962 100644 --- a/src/app/app.css +++ b/src/app/app.css @@ -142,6 +142,8 @@ body { .details, .gifts { background: linear-gradient(180deg, var(--cream-white) 0%, #F8F9F5 100%); padding: 4rem 0; + position: relative; + z-index: 1; } .rsvp, .message { @@ -156,6 +158,8 @@ body { .message { background: linear-gradient(135deg, var(--olive-green) 0%, var(--dark-olive) 100%); + position: relative; + z-index: 1; } /* Cards de detalhes */ @@ -314,6 +318,8 @@ body { color: var(--warm-gray); text-align: center; padding: 2rem 0; + position: relative; + z-index: 1; } .heart { @@ -345,12 +351,12 @@ body { width: 100vw; height: 100vh; } +} @media (max-width: 480px) { .floral-frame { padding: 1rem; margin: 0.5rem; } .detail-card { padding: 1rem; } -} - + .hero { padding: 0; margin: 0; @@ -360,3 +366,243 @@ body { width: 100vw; height: 100vh; } +} + +/* Formulário de Confirmação */ +.confirmation-form { + background: linear-gradient(180deg, var(--cream-white) 0%, #F8F9F5 100%); + padding: 4rem 0; + opacity: 0; + max-height: 0; + overflow: visible; + transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1); + transform: translateY(-20px); + position: relative; + z-index: 100; +} + +.confirmation-form.visible { + opacity: 1; + max-height: none; + overflow: visible; + transform: translateY(0); +} + +.confirmation-form h2 { + text-align: center; + font-size: clamp(1.75rem, 4vw, 2.5rem); + margin-bottom: 3rem; + color: var(--text-dark); +} + +.rsvp-form { + max-width: 700px; + margin: 0 auto; + background: var(--pure-white); + padding: 3rem; + border-radius: 15px; + box-shadow: 0 8px 24px var(--moss-shadow); + border: 1px solid rgba(156, 175, 136, 0.2); + position: relative; + z-index: 200; +} + +.form-group { + margin-bottom: 2rem; + position: relative; +} + +.form-group label { + display: block; + margin-bottom: 0.8rem; + font-weight: 600; + color: var(--text-dark); + font-size: 1.1rem; + font-family: "Georgia", "Times New Roman", serif; +} + +.form-input { + width: 100%; + padding: 1.2rem 1.5rem; + border: 2px solid var(--light-moss); + border-radius: 8px; + font-size: 1rem; + font-family: "Georgia", "Times New Roman", serif; + transition: all 0.3s ease; + background: var(--pure-white); + box-shadow: 0 2px 8px rgba(107, 142, 35, 0.08); +} + +.form-input:focus { + outline: none; + border-color: var(--olive-green); + box-shadow: 0 0 0 3px rgba(107, 142, 35, 0.15); +} + +.form-input::placeholder { + color: var(--warm-gray); + font-style: italic; +} + +.companion-section { + text-align: center; + margin: 3rem 0; + padding: 2rem; + background: rgba(156, 175, 136, 0.1); + border-radius: 12px; + border: 2px dashed var(--sage-green); +} + +.companion-fields { + margin-top: 3rem; + padding: 2rem; + background: rgba(156, 175, 136, 0.05); + border-radius: 12px; + border-left: 4px solid var(--sage-green); + animation: slideInUp 0.5s ease-out; +} + +@keyframes slideInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.companion-fields h3 { + margin-bottom: 2rem; + color: var(--text-dark); + text-align: center; + font-size: 1.3rem; + font-family: "Georgia", "Times New Roman", serif; +} + +.btn-text { + background: transparent; + color: var(--moss-green); + border: none; + padding: 0.8rem 1.5rem; + cursor: pointer; + font-size: 0.95rem; + margin-top: 1.5rem; + border-radius: 8px; + transition: all 0.3s ease; + font-family: "Georgia", "Times New Roman", serif; +} + +.btn-text:hover { + color: var(--dark-moss); + background: rgba(156, 175, 136, 0.1); +} + +.form-actions { + text-align: center; + margin-top: 3rem; + padding-top: 2rem; + border-top: 1px solid var(--light-moss); + position: relative; + z-index: 300; +} + +.btn-large { + padding: 1.2rem 3rem; + font-size: 1.1rem; + min-width: 250px; +} + +.btn:disabled { + background: var(--warm-gray); + cursor: not-allowed; + opacity: 0.6; +} + +.btn:disabled:hover { + transform: none; + box-shadow: none; +} + +/* Responsividade do formulário */ +@media (max-width: 768px) { + .confirmation-form { + padding: 3rem 0; + } + + .rsvp-form { + margin: 0 1rem; + padding: 2rem; + } + + .btn-large { + min-width: 240px; + padding: 1.2rem 2.5rem; + font-size: 1.1rem; + } + + .companion-section { + padding: 1.5rem; + margin: 2rem 0; + } + + .companion-fields { + padding: 2rem; + } + + .form-input { + padding: 1rem 1.2rem; + } +} + +@media (max-width: 480px) { + .confirmation-form { + padding: 2rem 0; + } + + .rsvp-form { + margin: 0 0.5rem; + padding: 1.5rem; + } + + .form-input { + padding: 0.9rem 1rem; + font-size: 0.95rem; + } + + .btn-large { + min-width: 200px; + padding: 1rem 2rem; + font-size: 1rem; + letter-spacing: 1px; + } + + .companion-section { + padding: 1rem; + margin: 1.5rem 0; + } + + .companion-section::before { + font-size: 1.5rem; + top: -12px; + } + + .companion-fields { + padding: 1.5rem; + } + + .form-group { + margin-bottom: 1.5rem; + } + + .confirmation-form h2 { + margin-bottom: 2rem; + } + + .form-actions { + margin-top: 2rem; + padding-top: 2rem; + } +} + diff --git a/src/app/app.html b/src/app/app.html index 23c4dd9..676a1b6 100644 --- a/src/app/app.html +++ b/src/app/app.html @@ -64,11 +64,110 @@

Confirme sua Presença

Você está convidado para celebrar o nosso grande dia.

Pedimos gentilmente que nos confirme até dia {{ weddingData.rsvpDeadline }}
26.09.2025 | 19:00h

- Confirmar +
+ +
+
+

Dados para Confirmação

+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ +
+ + +
+

Dados do Acompanhante

+ +
+ + +
+ +
+ + +
+ + +
+ + +
+ +
+
+
+
+
diff --git a/src/app/app.ts b/src/app/app.ts index 3146499..e860199 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -1,16 +1,111 @@ import { Component } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; import { environment } from '../environments/environment'; +interface GuestData { + firstName: string; + lastName: string; + phone: string; +} + +interface FormData { + guest: GuestData; + companion: GuestData; +} + @Component({ selector: 'app-root', standalone: true, - imports: [CommonModule], - templateUrl: './app.html' + imports: [CommonModule, FormsModule], + templateUrl: './app.html', + styleUrl: './app.css' }) export class AppComponent { title = 'wedding-invitation'; // Expondo as variáveis de ambiente para o template readonly weddingData = environment.wedding; + + // Controle do formulário + isFormVisible = false; + showCompanionFields = false; + + // Dados do formulário + formData: FormData = { + guest: { + firstName: '', + lastName: '', + phone: '' + }, + companion: { + firstName: '', + lastName: '', + phone: '' + } + }; + + showConfirmationForm() { + this.isFormVisible = true; + + // Aguarda o DOM ser atualizado antes de fazer o scroll + setTimeout(() => { + const formElement = document.getElementById('confirmationForm'); + if (formElement) { + formElement.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + } + }, 100); + } + + addCompanion() { + this.showCompanionFields = true; + } + + removeCompanion() { + this.showCompanionFields = false; + // Limpa os dados do acompanhante + this.formData.companion = { + firstName: '', + lastName: '', + phone: '' + }; + } + + sendConfirmation() { + // Validação básica + if (!this.formData.guest.firstName || !this.formData.guest.lastName || !this.formData.guest.phone) { + alert('Por favor, preencha todos os campos obrigatórios do convidado principal.'); + return; + } + + // Validação do acompanhante se os campos estiverem visíveis + if (this.showCompanionFields && (!this.formData.companion.firstName || !this.formData.companion.lastName)) { + alert('Por favor, preencha todos os campos do acompanhante ou remova-o.'); + return; + } + + const guestName = `${this.formData.guest.firstName} ${this.formData.guest.lastName}`; + let message = `Olá! Confirmo presença no casamento de ${this.weddingData.bride.name} & ${this.weddingData.groom.name}!\n\n`; + message += `*Convidado Principal:*\n`; + message += `Nome: ${guestName}\n`; + message += `Telefone: ${this.formData.guest.phone}\n`; + + if (this.showCompanionFields && this.formData.companion.firstName) { + const companionName = `${this.formData.companion.firstName} ${this.formData.companion.lastName}`; + message += `\n*Acompanhante:*\n`; + message += `Nome: ${companionName}\n`; + } + + message += `\nAguardamos vocês no nosso grande dia! 💚`; + + // Usa o número do WhatsApp do environment + const whatsappNumber = this.weddingData.whatsappNumber; + const whatsappUrl = `https://wa.me/${whatsappNumber}?text=${encodeURIComponent(message)}`; + + // Abre o WhatsApp + window.open(whatsappUrl, '_blank'); + } } diff --git a/src/environments/environment.interface.ts b/src/environments/environment.interface.ts new file mode 100644 index 0000000..bc03dc1 --- /dev/null +++ b/src/environments/environment.interface.ts @@ -0,0 +1,34 @@ +export interface WeddingData { + bride: { + name: string; + }; + groom: { + name: string; + }; + ceremony: { + venue: string; + address: string; + }; + reception: { + venue: string; + address: string; + }; + dressCode: string; + date: string; + fullDate: string; + time: string; + rsvpDeadline: string; + rsvpLink: string; + whatsappNumber: string; + whatsappLink: string; + message: string; + giftInfo: { + message: string; + link: string; + }; +} + +export interface Environment { + production: boolean; + wedding: WeddingData; +} diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index bfabc8c..20b6e51 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,6 +1,8 @@ +import { Environment } from './environment.interface'; + // Environment para PRODUÇÃO (GitHub Pages) // Dados substituídos automaticamente durante o build via GitHub Secrets -export const environment = { +export const environment: Environment = { production: true, wedding: { bride: { @@ -23,6 +25,7 @@ export const environment = { time: 'Horário', rsvpDeadline: 'Data Limite RSVP', rsvpLink: '#', + whatsappNumber: 'Número do WhatsApp', whatsappLink: '#', message: 'Uma mensagem especial sobre o amor e a celebração.', giftInfo: { From 631391d2c31faa2973c883ffe5e86c07e1cfd972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Evandro=20Pican=C3=A7o?= <6420942+expectpin@users.noreply.github.com> Date: Thu, 4 Sep 2025 10:10:36 -0400 Subject: [PATCH 2/2] feat: add interactive RSVP form with WhatsApp integration - Replace static RSVP link with expandable form - Add guest and companion fields with validation - Implement WhatsApp message formatting and integration - Add smooth scroll animation and form expansion - Update environment structure to support whatsappNumber - Fix replace-env.js script to handle all environment variables - Preserve original green olive/moss color palette --- scripts/replace-env.js | 13 +- src/app/app.css | 609 +-------------------------- src/environments/environment.prod.ts | 7 +- src/styles.css | 492 ++++++++++++++++++++++ 4 files changed, 506 insertions(+), 615 deletions(-) diff --git a/scripts/replace-env.js b/scripts/replace-env.js index 0d2f09b..81b5197 100644 --- a/scripts/replace-env.js +++ b/scripts/replace-env.js @@ -15,7 +15,9 @@ function createDevEnvironment() { // Template genérico apenas para desenvolvimento/CI quando não existe arquivo local const envDevTemplate = `// Environment para DESENVOLVIMENTO/TESTES (gerado automaticamente) -export const environment = { +import { Environment } from './environment.interface'; + +export const environment: Environment = { production: false, wedding: { bride: { name: 'Test Bride' }, @@ -34,6 +36,7 @@ export const environment = { time: '18:00', rsvpDeadline: '01 de dezembro de 2024', rsvpLink: 'https://example.com/rsvp', + whatsappNumber: '5500000000000', whatsappLink: 'https://wa.me/5500000000000', message: 'Test wedding message for development and testing.', giftInfo: { @@ -63,12 +66,13 @@ function replaceEnvironmentVariables() { CEREMONY_ADDRESS: process.env.CEREMONY_ADDRESS || 'Endereço da Cerimônia, 123', RECEPTION_VENUE: process.env.RECEPTION_VENUE || 'Local da Recepção', RECEPTION_ADDRESS: process.env.RECEPTION_ADDRESS || 'Endereço da Recepção, 456', + DRESS_CODE: process.env.DRESS_CODE || 'Venha com sua melhor roupa social e aproveite a celebração conosco.', WEDDING_DATE: process.env.WEDDING_DATE || 'Mês/Ano', WEDDING_FULL_DATE: process.env.WEDDING_FULL_DATE || 'Data Completa do Casamento', WEDDING_TIME: process.env.WEDDING_TIME || 'Horário', - DRESS_CODE: process.env.DRESS_CODE || 'Traje', RSVP_DEADLINE: process.env.RSVP_DEADLINE || 'Data Limite RSVP', RSVP_LINK: process.env.RSVP_LINK || '#', + WHATSAPP_NUMBER: process.env.WHATSAPP_NUMBER || '5500000000000', WHATSAPP_LINK: process.env.WHATSAPP_LINK || '#', WEDDING_MESSAGE: process.env.WEDDING_MESSAGE || 'Uma mensagem especial sobre o amor e a celebração.', GIFT_MESSAGE: process.env.GIFT_MESSAGE || 'Sua presença já é nosso maior presente!', @@ -85,7 +89,9 @@ function replaceEnvironmentVariables() { // Template do arquivo de produção com valores reais const envProdTemplate = `// Environment para PRODUÇÃO (GitHub Pages) -export const environment = { +import { Environment } from './environment.interface'; + +export const environment: Environment = { production: true, wedding: { bride: { @@ -108,6 +114,7 @@ export const environment = { time: '${envVars.WEDDING_TIME}', rsvpDeadline: '${envVars.RSVP_DEADLINE}', rsvpLink: '${envVars.RSVP_LINK}', + whatsappNumber: '${envVars.WHATSAPP_NUMBER}', whatsappLink: '${envVars.WHATSAPP_LINK}', message: '${envVars.WEDDING_MESSAGE}', giftInfo: { diff --git a/src/app/app.css b/src/app/app.css index 73b4962..7af77f8 100644 --- a/src/app/app.css +++ b/src/app/app.css @@ -1,608 +1 @@ -/* Paleta de cores otimizada */ -:root { - --olive-green: #6B8E23; - --dark-olive: #556B2F; - --light-olive: #9ACD32; - --moss-green: #8A9A5B; - --dark-moss: #5D6B4A; - --light-moss: #A8B885; - --sage-green: #9CAF88; - --cream-white: #FFF8F3; - --pure-white: #FFFFFF; - --text-dark: #2F3E46; - --text-light: #52796F; - --warm-gray: #8B7E74; - --shadow: rgba(107, 142, 35, 0.1); - --moss-shadow: rgba(138, 154, 91, 0.15); -} - -/* Reset e base */ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: "Georgia", "Times New Roman", serif; - line-height: 1.6; - color: var(--text-dark); - overflow-x: hidden; -} - -.container { - max-width: 1200px; - margin: 0 auto; - padding: 0 1rem; -} - -/* Layout principal */ -.wedding-invitation { - width: 100%; - min-height: 100vh; -} - -/* Hero Section */ -.hero { - position: relative; - background: linear-gradient(135deg, var(--cream-white) 0%, var(--pure-white) 50%, #F5F7F0 100%); - min-height: 100vh; - display: flex; - align-items: center; - justify-content: center; - text-align: center; - padding: 2rem 1rem; -} - -.hero::before { - content: ''; - position: absolute; - inset: 0; - background: - radial-gradient(circle at 25% 25%, rgba(107, 142, 35, 0.15) 0%, transparent 50%), - radial-gradient(circle at 75% 75%, rgba(138, 154, 91, 0.15) 0%, transparent 50%); - opacity: 0.08; - z-index: 1; -} - -.hero-content { - position: relative; - z-index: 2; - max-width: 800px; -} - -/* Moldura floral */ -.floral-frame { - position: relative; - padding: 2rem; - border-radius: 20px; - background: rgba(255, 255, 255, 0.9); - backdrop-filter: blur(10px); - box-shadow: 0 8px 32px var(--shadow); - border: 2px solid rgba(138, 154, 91, 0.2); -} - -.floral-frame::before { - content: ''; - position: absolute; - inset: -10px; - background: linear-gradient(45deg, var(--olive-green), var(--moss-green), var(--sage-green), var(--moss-green), var(--olive-green)); - border-radius: 25px; - opacity: 0.1; - z-index: -1; -} - -.floral-frame::after { - content: '🌿'; - position: absolute; - top: -15px; - left: 50%; - transform: translateX(-50%); - font-size: 2rem; - background: var(--cream-white); - padding: 0 1rem; - border-radius: 50px; -} - -/* Typography */ -.couple-names { - font-size: clamp(2rem, 5vw, 4rem); - font-weight: 300; - margin-bottom: 1rem; -} - -.bride-name { - color: var(--moss-green); - text-shadow: 1px 1px 2px rgba(138, 154, 91, 0.2); -} - -.groom-name { - color: var(--olive-green); - text-shadow: 1px 1px 2px rgba(107, 142, 35, 0.2); -} - -.ampersand { - color: var(--sage-green); - font-style: italic; - margin: 0 1rem; -} - -.wedding-date { - font-size: clamp(1.2rem, 3vw, 1.5rem); - margin: 1rem 0; -} - -.celebration-text { - font-size: clamp(1rem, 2.5vw, 1.2rem); - color: var(--text-light); - font-style: italic; -} - -/* Seções principais */ -.details, .gifts { - background: linear-gradient(180deg, var(--cream-white) 0%, #F8F9F5 100%); - padding: 4rem 0; - position: relative; - z-index: 1; -} - -.rsvp, .message { - padding: 4rem 0; - text-align: center; - color: var(--pure-white); -} - -.rsvp { - background: linear-gradient(135deg, var(--moss-green) 0%, var(--dark-moss) 100%); -} - -.message { - background: linear-gradient(135deg, var(--olive-green) 0%, var(--dark-olive) 100%); - position: relative; - z-index: 1; -} - -/* Cards de detalhes */ -.details .container { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); -} - -.detail-card { - background: var(--pure-white); - border-radius: 12px; - padding: 2rem; - display: flex; - align-items: flex-start; - box-shadow: 0 4px 12px var(--shadow); - border-left: 4px solid var(--olive-green); - transition: all 0.3s ease; - position: relative; -} - -.detail-card:nth-child(even) { - border-left-color: var(--moss-green); -} - -.detail-card::before { - content: ''; - position: absolute; - top: 0; - right: 0; - border: 15px solid transparent; - border-right-color: var(--light-olive); - border-bottom-color: var(--light-olive); -} - -.detail-card:nth-child(even)::before { - border-right-color: var(--light-moss); - border-bottom-color: var(--light-moss); -} - -.detail-card:hover { - transform: translateY(-3px); - box-shadow: 0 8px 24px var(--moss-shadow); -} - -.detail-card h3 { - font-size: 1.5rem; - margin-bottom: 0.5rem; -} - -.detail-card p { - color: var(--text-light); - margin: 0.25rem 0; -} - -/* Botões */ -.btn { - display: inline-block; - padding: 1rem 2rem; - border-radius: 25px; - text-decoration: none; - font-weight: 600; - font-size: 1rem; - transition: all 0.3s ease; - border: none; - cursor: pointer; - text-align: center; - min-width: 200px; - text-transform: uppercase; - letter-spacing: 1px; - margin: 0.5rem; -} - -.btn-primary { - background: var(--olive-green); - color: var(--pure-white); - box-shadow: 0 4px 15px rgba(107, 142, 35, 0.3); -} - -.btn-primary:hover { - background: var(--dark-olive); - transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(107, 142, 35, 0.4); -} - -.btn-secondary { - background: var(--pure-white); - color: var(--moss-green); - border: 2px solid var(--pure-white); - box-shadow: 0 4px 15px rgba(255, 255, 255, 0.2); -} - -.btn-secondary:hover { - background: var(--cream-white); - color: var(--dark-moss); - transform: translateY(-2px); -} - -.btn-outline { - background: transparent; - color: var(--olive-green); - border: 2px solid var(--olive-green); -} - -.btn-outline:hover { - background: var(--olive-green); - color: var(--pure-white); -} - -/* Elementos especiais */ -.rsvp-deadline { - font-weight: bold; - font-size: 1.2rem; - background: rgba(255, 255, 255, 0.1); - padding: 1rem; - border-radius: 8px; - display: inline-block; - margin: 1.5rem 0; -} - -.signature { - font-style: italic; - font-size: 1.2rem; - background: rgba(255, 255, 255, 0.1); - padding: 1rem 2rem; - border-radius: 15px; - display: inline-block; - margin-top: 2rem; -} - -.rsvp h2, .message h2, .gifts h2 { - font-size: clamp(1.75rem, 4vw, 2.5rem); - margin-bottom: 1rem; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2); -} - -.gifts h2 { - color: var(--text-dark); - text-shadow: none; -} - -.rsvp p, .message p { - font-size: 1.1rem; - color: var(--cream-white); - margin: 0.5rem 0; -} - -.gifts p { - color: var(--text-light); - max-width: 600px; - margin: 1rem auto 2rem; -} - -/* Footer */ -.footer { - background: var(--text-dark); - color: var(--warm-gray); - text-align: center; - padding: 2rem 0; - position: relative; - z-index: 1; -} - -.heart { - font-size: 2rem; - margin-top: 1rem; - color: var(--moss-green); - animation: heartbeat 2s ease-in-out infinite; -} - -/* Animações */ -@keyframes heartbeat { - 0%, 100% { transform: scale(1); } - 50% { transform: scale(1.1); } -} - -/* Responsividade */ -@media (max-width: 768px) { - .container { padding: 0 0.5rem; } - .hero { padding: 1rem 0.5rem; min-height: 90vh; } - .floral-frame { padding: 1.5rem; margin: 1rem; } - .floral-frame::after { font-size: 1.5rem; } - .ampersand { margin: 0 0.5rem; } - .hero { - padding: 0; - margin: 0; - height: 100vh; - } - .hero-image { - width: 100vw; - height: 100vh; - } -} - -@media (max-width: 480px) { - .floral-frame { padding: 1rem; margin: 0.5rem; } - .detail-card { padding: 1rem; } - - .hero { - padding: 0; - margin: 0; - height: 100vh; - } - .hero-image { - width: 100vw; - height: 100vh; - } -} - -/* Formulário de Confirmação */ -.confirmation-form { - background: linear-gradient(180deg, var(--cream-white) 0%, #F8F9F5 100%); - padding: 4rem 0; - opacity: 0; - max-height: 0; - overflow: visible; - transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1); - transform: translateY(-20px); - position: relative; - z-index: 100; -} - -.confirmation-form.visible { - opacity: 1; - max-height: none; - overflow: visible; - transform: translateY(0); -} - -.confirmation-form h2 { - text-align: center; - font-size: clamp(1.75rem, 4vw, 2.5rem); - margin-bottom: 3rem; - color: var(--text-dark); -} - -.rsvp-form { - max-width: 700px; - margin: 0 auto; - background: var(--pure-white); - padding: 3rem; - border-radius: 15px; - box-shadow: 0 8px 24px var(--moss-shadow); - border: 1px solid rgba(156, 175, 136, 0.2); - position: relative; - z-index: 200; -} - -.form-group { - margin-bottom: 2rem; - position: relative; -} - -.form-group label { - display: block; - margin-bottom: 0.8rem; - font-weight: 600; - color: var(--text-dark); - font-size: 1.1rem; - font-family: "Georgia", "Times New Roman", serif; -} - -.form-input { - width: 100%; - padding: 1.2rem 1.5rem; - border: 2px solid var(--light-moss); - border-radius: 8px; - font-size: 1rem; - font-family: "Georgia", "Times New Roman", serif; - transition: all 0.3s ease; - background: var(--pure-white); - box-shadow: 0 2px 8px rgba(107, 142, 35, 0.08); -} - -.form-input:focus { - outline: none; - border-color: var(--olive-green); - box-shadow: 0 0 0 3px rgba(107, 142, 35, 0.15); -} - -.form-input::placeholder { - color: var(--warm-gray); - font-style: italic; -} - -.companion-section { - text-align: center; - margin: 3rem 0; - padding: 2rem; - background: rgba(156, 175, 136, 0.1); - border-radius: 12px; - border: 2px dashed var(--sage-green); -} - -.companion-fields { - margin-top: 3rem; - padding: 2rem; - background: rgba(156, 175, 136, 0.05); - border-radius: 12px; - border-left: 4px solid var(--sage-green); - animation: slideInUp 0.5s ease-out; -} - -@keyframes slideInUp { - from { - opacity: 0; - transform: translateY(20px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.companion-fields h3 { - margin-bottom: 2rem; - color: var(--text-dark); - text-align: center; - font-size: 1.3rem; - font-family: "Georgia", "Times New Roman", serif; -} - -.btn-text { - background: transparent; - color: var(--moss-green); - border: none; - padding: 0.8rem 1.5rem; - cursor: pointer; - font-size: 0.95rem; - margin-top: 1.5rem; - border-radius: 8px; - transition: all 0.3s ease; - font-family: "Georgia", "Times New Roman", serif; -} - -.btn-text:hover { - color: var(--dark-moss); - background: rgba(156, 175, 136, 0.1); -} - -.form-actions { - text-align: center; - margin-top: 3rem; - padding-top: 2rem; - border-top: 1px solid var(--light-moss); - position: relative; - z-index: 300; -} - -.btn-large { - padding: 1.2rem 3rem; - font-size: 1.1rem; - min-width: 250px; -} - -.btn:disabled { - background: var(--warm-gray); - cursor: not-allowed; - opacity: 0.6; -} - -.btn:disabled:hover { - transform: none; - box-shadow: none; -} - -/* Responsividade do formulário */ -@media (max-width: 768px) { - .confirmation-form { - padding: 3rem 0; - } - - .rsvp-form { - margin: 0 1rem; - padding: 2rem; - } - - .btn-large { - min-width: 240px; - padding: 1.2rem 2.5rem; - font-size: 1.1rem; - } - - .companion-section { - padding: 1.5rem; - margin: 2rem 0; - } - - .companion-fields { - padding: 2rem; - } - - .form-input { - padding: 1rem 1.2rem; - } -} - -@media (max-width: 480px) { - .confirmation-form { - padding: 2rem 0; - } - - .rsvp-form { - margin: 0 0.5rem; - padding: 1.5rem; - } - - .form-input { - padding: 0.9rem 1rem; - font-size: 0.95rem; - } - - .btn-large { - min-width: 200px; - padding: 1rem 2rem; - font-size: 1rem; - letter-spacing: 1px; - } - - .companion-section { - padding: 1rem; - margin: 1.5rem 0; - } - - .companion-section::before { - font-size: 1.5rem; - top: -12px; - } - - .companion-fields { - padding: 1.5rem; - } - - .form-group { - margin-bottom: 1.5rem; - } - - .confirmation-form h2 { - margin-bottom: 2rem; - } - - .form-actions { - margin-top: 2rem; - padding-top: 2rem; - } -} - +/* Este arquivo está sendo mantido vazio pois styles.css é o arquivo principal de estilos */ \ No newline at end of file diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 20b6e51..6e935b7 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -1,7 +1,6 @@ +// Environment para PRODUÇÃO (GitHub Pages) import { Environment } from './environment.interface'; -// Environment para PRODUÇÃO (GitHub Pages) -// Dados substituídos automaticamente durante o build via GitHub Secrets export const environment: Environment = { production: true, wedding: { @@ -19,13 +18,13 @@ export const environment: Environment = { venue: 'Local da Recepção', address: 'Endereço da Recepção, 456' }, - dressCode: 'Por favor, venha com sua melhor roupa social e aproveite a celebração conosco!', + dressCode: 'Traje social elegante - venha celebrar conosco!', date: 'Mês/Ano', fullDate: 'Data Completa do Casamento', time: 'Horário', rsvpDeadline: 'Data Limite RSVP', rsvpLink: '#', - whatsappNumber: 'Número do WhatsApp', + whatsappNumber: '5500000000000', whatsappLink: '#', message: 'Uma mensagem especial sobre o amor e a celebração.', giftInfo: { diff --git a/src/styles.css b/src/styles.css index 0112320..e8adc9c 100644 --- a/src/styles.css +++ b/src/styles.css @@ -741,3 +741,495 @@ img { animation: fadeIn 1s ease-out; animation-fill-mode: both; } + +/* =========================================== + FORMULÁRIO DE CONFIRMAÇÃO + =========================================== */ + +/* Seção do formulário de confirmação - transparente para não interferir nas cores */ +.confirmation-form { + background: transparent !important; + padding: 2rem 0 4rem 0; + opacity: 0; + max-height: 0; + overflow: visible; + transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1); + transform: translateY(-20px); + position: relative; + z-index: 100; +} + +.confirmation-form.visible { + opacity: 1; + max-height: none; + overflow: visible; + transform: translateY(0); +} + +.confirmation-form h2 { + text-align: center; + font-size: clamp(1.75rem, 4vw, 2.5rem); + margin-bottom: 3rem; + color: var(--branco); + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2); +} + +/* Cartão do formulário */ +.rsvp-form { + max-width: 700px; + margin: 0 auto; + background: var(--branco); + padding: 3rem; + border-radius: 15px; + box-shadow: 0 8px 24px var(--sombra); + border: 1px solid rgba(156, 175, 136, 0.2); + position: relative; + z-index: 200; +} + +/* Grupos de campos */ +.form-group { + margin-bottom: 2rem; + position: relative; +} + +.form-group label { + display: block; + margin-bottom: 0.8rem; + font-weight: 600; + color: var(--texto-escuro); + font-size: 1.1rem; + font-family: "Georgia", "Times New Roman", serif; +} + +/* Campos de entrada */ +.form-input { + width: 100%; + padding: 1.2rem 1.5rem; + border: 2px solid var(--verde-oliva-claro); + border-radius: 8px; + font-size: 1rem; + font-family: "Georgia", "Times New Roman", serif; + transition: all 0.3s ease; + background: var(--branco); + box-shadow: 0 2px 8px var(--sombra); +} + +.form-input:focus { + outline: none; + border-color: var(--verde-oliva); + box-shadow: 0 0 0 3px rgba(27, 89, 41, 0.15); +} + +.form-input::placeholder { + color: #8B7E74; + font-style: italic; +} + +/* Seção de acompanhante */ +.companion-section { + text-align: center; + margin: 3rem 0; + padding: 2rem; + background: rgba(156, 175, 136, 0.1); + border-radius: 12px; + border: 2px dashed var(--verde-oliva-claro); +} + +.companion-fields { + margin-top: 3rem; + padding: 2rem; + background: rgba(156, 175, 136, 0.05); + border-radius: 12px; + border-left: 4px solid var(--verde-oliva-claro); + animation: slideInUp 0.5s ease-out; +} + +@keyframes slideInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.companion-fields h3 { + margin-bottom: 2rem; + color: var(--texto-escuro); + text-align: center; + font-size: 1.3rem; + font-family: "Georgia", "Times New Roman", serif; +} + +/* Botão de texto para remover acompanhante */ +.btn-text { + background: transparent; + color: var(--verde-oliva-medio); + border: none; + padding: 0.8rem 1.5rem; + cursor: pointer; + font-size: 0.95rem; + margin-top: 1.5rem; + border-radius: 8px; + transition: all 0.3s ease; + font-family: "Georgia", "Times New Roman", serif; +} + +.btn-text:hover { + color: var(--verde-oliva); + background: rgba(156, 175, 136, 0.1); +} + +/* Área de ações do formulário */ +.form-actions { + text-align: center; + margin-top: 3rem; + padding-top: 2rem; + border-top: 1px solid var(--verde-oliva-claro); + position: relative; + z-index: 300; +} + +/* Botão grande */ +.btn-large { + padding: 1.2rem 3rem; + font-size: 1.1rem; + min-width: 250px; +} + +/* Estados do botão desabilitado */ +.btn:disabled { + background: #8B7E74; + cursor: not-allowed; + opacity: 0.6; +} + +.btn:disabled:hover { + transform: none; + box-shadow: none; +} + +/* Responsividade do formulário */ +@media (max-width: 768px) { + .confirmation-form { + padding: 3rem 0; + } + + .rsvp-form { + margin: 0 1rem; + padding: 2rem; + } + + .btn-large { + min-width: 240px; + padding: 1.2rem 2.5rem; + font-size: 1.1rem; + } + + .companion-section { + padding: 1.5rem; + margin: 2rem 0; + } + + .companion-fields { + padding: 2rem; + } + + .form-input { + padding: 1rem 1.2rem; + } +} + +@media (max-width: 480px) { + .confirmation-form { + padding: 2rem 0; + } + + .rsvp-form { + margin: 0 0.5rem; + padding: 1.5rem; + } + + .form-input { + padding: 0.9rem 1rem; + font-size: 0.95rem; + } + + .btn-large { + min-width: 200px; + padding: 1rem 2rem; + font-size: 1rem; + letter-spacing: 1px; + } + + .companion-section { + padding: 1rem; + margin: 1.5rem 0; + } + + .companion-fields { + padding: 1.5rem; + } + + .form-group { + margin-bottom: 1.5rem; + } + + .confirmation-form h2 { + margin-bottom: 2rem; + } + + .form-actions { + margin-top: 2rem; + padding-top: 2rem; + } +} + +/* =========================================== + FORMULÁRIO DE CONFIRMAÇÃO + =========================================== */ + +/* Seção do formulário de confirmação */ +.confirmation-form { + background: transparent !important; + padding: 2rem 0 4rem 0; + opacity: 0; + max-height: 0; + overflow: visible; + transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1); + transform: translateY(-20px); + position: relative; + z-index: 100; +} + +.confirmation-form.visible { + opacity: 1; + max-height: none; + overflow: visible; + transform: translateY(0); +} + +.confirmation-form h2 { + text-align: center; + font-size: clamp(1.75rem, 4vw, 2.5rem); + margin-bottom: 3rem; + color: var(--branco); + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2); +} + +/* Cartão do formulário */ +.rsvp-form { + max-width: 700px; + margin: 0 auto; + background: var(--branco); + padding: 3rem; + border-radius: 15px; + box-shadow: 0 8px 24px var(--sombra); + border: 1px solid rgba(156, 175, 136, 0.2); + position: relative; + z-index: 200; +} + +/* Grupos de campos */ +.form-group { + margin-bottom: 2rem; + position: relative; +} + +.form-group label { + display: block; + margin-bottom: 0.8rem; + font-weight: 600; + color: var(--texto-escuro); + font-size: 1.1rem; + font-family: "Georgia", "Times New Roman", serif; +} + +/* Campos de entrada */ +.form-input { + width: 100%; + padding: 1.2rem 1.5rem; + border: 2px solid var(--verde-oliva-claro); + border-radius: 8px; + font-size: 1rem; + font-family: "Georgia", "Times New Roman", serif; + transition: all 0.3s ease; + background: var(--branco); + box-shadow: 0 2px 8px var(--sombra); +} + +.form-input:focus { + outline: none; + border-color: var(--verde-oliva); + box-shadow: 0 0 0 3px rgba(27, 89, 41, 0.15); +} + +.form-input::placeholder { + color: var(--texto-claro); + font-style: italic; +} + +/* Seção de acompanhante */ +.companion-section { + text-align: center; + margin: 3rem 0; + padding: 2rem; + background: rgba(156, 175, 136, 0.1); + border-radius: 12px; + border: 2px dashed var(--verde-oliva-claro); +} + +.companion-fields { + margin-top: 3rem; + padding: 2rem; + background: rgba(156, 175, 136, 0.05); + border-radius: 12px; + border-left: 4px solid var(--verde-oliva-claro); + animation: slideInUp 0.5s ease-out; +} + +@keyframes slideInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.companion-fields h3 { + margin-bottom: 2rem; + color: var(--texto-escuro); + text-align: center; + font-size: 1.3rem; + font-family: "Georgia", "Times New Roman", serif; +} + +/* Botão de texto para remover acompanhante */ +.btn-text { + background: transparent; + color: var(--verde-oliva-medio); + border: none; + padding: 0.8rem 1.5rem; + cursor: pointer; + font-size: 0.95rem; + margin-top: 1.5rem; + border-radius: 8px; + transition: all 0.3s ease; + font-family: "Georgia", "Times New Roman", serif; +} + +.btn-text:hover { + color: var(--verde-oliva); + background: rgba(156, 175, 136, 0.1); +} + +/* Área de ações do formulário */ +.form-actions { + text-align: center; + margin-top: 3rem; + padding-top: 2rem; + border-top: 1px solid var(--verde-oliva-claro); + position: relative; + z-index: 300; +} + +/* Botão grande */ +.btn-large { + padding: 1.2rem 3rem; + font-size: 1.1rem; + min-width: 250px; +} + +/* Estados do botão desabilitado */ +.btn:disabled { + background: var(--cinza-medio); + cursor: not-allowed; + opacity: 0.6; +} + +.btn:disabled:hover { + transform: none; + box-shadow: none; +} + +/* Responsividade do formulário mobile */ +@media (max-width: 768px) { + .confirmation-form { + padding: 3rem 0; + } + + .rsvp-form { + margin: 0 1rem; + padding: 2rem; + } + + .btn-large { + min-width: 240px; + padding: 1.2rem 2.5rem; + font-size: 1.1rem; + } + + .companion-section { + padding: 1.5rem; + margin: 2rem 0; + } + + .companion-fields { + padding: 2rem; + } + + .form-input { + padding: 1rem 1.2rem; + } +} + +@media (max-width: 480px) { + .confirmation-form { + padding: 2rem 0; + } + + .rsvp-form { + margin: 0 0.5rem; + padding: 1.5rem; + } + + .form-input { + padding: 0.9rem 1rem; + font-size: 0.95rem; + } + + .btn-large { + min-width: 200px; + padding: 1rem 2rem; + font-size: 1rem; + letter-spacing: 1px; + } + + .companion-section { + padding: 1rem; + margin: 1.5rem 0; + } + + .companion-fields { + padding: 1.5rem; + } + + .form-group { + margin-bottom: 1.5rem; + } + + .confirmation-form h2 { + margin-bottom: 2rem; + } + + .form-actions { + margin-top: 2rem; + padding-top: 2rem; + } +}