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 @@
Você está convidado para celebrar o nosso grande dia.
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;
+ }
+}