feat(ui): add wedding theme styles and layout components
* Introduced wedding-themed CSS variables for styling. * Created layout component for the wedding site with navigation and countdown. * Added RSVP and photo upload pages with form handling. * Implemented QR code page for wedding site access. * Configured TypeScript and Vite for the project. * Added robots.txt for search engine crawling.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Server ServerConfig `yaml:"server"`
|
||||
Site SiteConfig `yaml:"site"`
|
||||
Wedding WeddingConfig `yaml:"wedding"`
|
||||
Storage StorageConfig `yaml:"storage"`
|
||||
Email EmailConfig `yaml:"email"`
|
||||
Upload UploadConfig `yaml:"upload"`
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
Port int `yaml:"port"`
|
||||
}
|
||||
|
||||
type SiteConfig struct {
|
||||
URL string `yaml:"url"`
|
||||
}
|
||||
|
||||
type WeddingConfig struct {
|
||||
Date time.Time `yaml:"date"`
|
||||
CeremonyTime string `yaml:"ceremony_time"`
|
||||
RSVPBy time.Time `yaml:"rsvp_by"`
|
||||
VenueName string `yaml:"venue_name"`
|
||||
VenueAddress string `yaml:"venue_address"`
|
||||
RSVPPhone string `yaml:"rsvp_phone"`
|
||||
}
|
||||
|
||||
type StorageConfig struct {
|
||||
DataDir string `yaml:"data_dir"`
|
||||
}
|
||||
|
||||
type EmailConfig struct {
|
||||
SMTPHost string `yaml:"smtp_host"`
|
||||
SMTPPort int `yaml:"smtp_port"`
|
||||
SMTPUser string `yaml:"smtp_user"`
|
||||
SMTPPass string `yaml:"smtp_pass"`
|
||||
From string `yaml:"from"`
|
||||
To string `yaml:"to"`
|
||||
}
|
||||
|
||||
type UploadConfig struct {
|
||||
MaxSizeMB int `yaml:"max_size_mb"`
|
||||
MaxFiles int `yaml:"max_files"`
|
||||
}
|
||||
|
||||
// Path resolves the config file location: $CONFIG_PATH, or ./config.yaml.
|
||||
func Path() string {
|
||||
if p := os.Getenv("CONFIG_PATH"); p != "" {
|
||||
return p
|
||||
}
|
||||
return "config.yaml"
|
||||
}
|
||||
|
||||
func Load(path string) (*Config, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("reading config %s: %w", path, err)
|
||||
}
|
||||
|
||||
var cfg Config
|
||||
if err := yaml.Unmarshal(data, &cfg); err != nil {
|
||||
return nil, fmt.Errorf("parsing config %s: %w", path, err)
|
||||
}
|
||||
|
||||
if cfg.Server.Port == 0 {
|
||||
cfg.Server.Port = 8080
|
||||
}
|
||||
if cfg.Storage.DataDir == "" {
|
||||
cfg.Storage.DataDir = "./data"
|
||||
}
|
||||
if cfg.Upload.MaxSizeMB == 0 {
|
||||
cfg.Upload.MaxSizeMB = 15
|
||||
}
|
||||
if cfg.Upload.MaxFiles == 0 {
|
||||
cfg.Upload.MaxFiles = 10
|
||||
}
|
||||
if cfg.Wedding.Date.IsZero() {
|
||||
return nil, fmt.Errorf("wedding.date is required in %s", path)
|
||||
}
|
||||
if cfg.Wedding.RSVPBy.IsZero() {
|
||||
return nil, fmt.Errorf("wedding.rsvp_by is required in %s", path)
|
||||
}
|
||||
|
||||
return &cfg, nil
|
||||
}
|
||||
Reference in New Issue
Block a user