diff --git a/models/auth.go b/models/auth.go
new file mode 100644
index 0000000..501ad67
--- /dev/null
+++ b/models/auth.go
@@ -0,0 +1,103 @@
+package models
+
+// AppInfo represents an application requesting authorization
+type AppInfo struct {
+ Name string
+ Domain string
+ LogoIcon string
+ Verified bool
+}
+
+// WalletInfo represents a user's wallet details
+type WalletInfo struct {
+ Name string
+ Address string
+ Balance string
+}
+
+// TokenAmount represents a token amount with its value
+type TokenAmount struct {
+ Symbol string
+ Amount string
+ USD string
+ Initials string
+}
+
+// TxDetails represents transaction details for authorization
+type TxDetails struct {
+ Type string
+ FromToken TokenAmount
+ ToToken TokenAmount
+ Network string
+ NetworkFee string
+ MaxFee string
+ Slippage string
+ Contract string
+ Function string
+ RawData string
+}
+
+// AuthRequest represents an authorization request from an app
+type AuthRequest struct {
+ Type string
+ App AppInfo
+ Wallet WalletInfo
+ Message string
+ MessageHex string
+ Transaction *TxDetails
+}
+
+// DefaultAuthRequest returns a sample authorization request for testing
+func DefaultAuthRequest(reqType string) AuthRequest {
+ if reqType == "" {
+ reqType = "connect"
+ }
+
+ return AuthRequest{
+ Type: reqType,
+ App: AppInfo{
+ Name: "Uniswap",
+ Domain: "app.uniswap.org",
+ LogoIcon: "cube",
+ Verified: true,
+ },
+ Wallet: WalletInfo{
+ Name: "Main Wallet",
+ Address: "sonr1x9f...7k2m",
+ Balance: "1,234.56 SNR",
+ },
+ Message: `Welcome to Uniswap!
+
+Click to sign in and accept the Uniswap Terms of Service.
+
+This request will not trigger a blockchain transaction or cost any gas fees.
+
+Wallet address:
+sonr1x9f4h2k8m3n5p7q2r4s6t8v0w3x5y7z9a1b3c5d7k2m
+
+Nonce: 8f4a2b1c`,
+ MessageHex: "0x57656c636f6d6520746f20556e697377617021...",
+ Transaction: &TxDetails{
+ Type: "Swap",
+ FromToken: TokenAmount{
+ Symbol: "ETH",
+ Amount: "100.00",
+ USD: "$234,567.00",
+ Initials: "E",
+ },
+ ToToken: TokenAmount{
+ Symbol: "USDC",
+ Amount: "125,000",
+ USD: "$125,000.00",
+ Initials: "U",
+ },
+ Network: "Sonr Mainnet",
+ NetworkFee: "~$0.12",
+ MaxFee: "$0.26",
+ Slippage: "0.5%",
+ Contract: "0x7a25...3f8b",
+ Function: "swapExactTokensForTokens()",
+ RawData: "0x38ed1739\n0000000000000000000000000000000000000056bc75e2d63100000...",
+ },
+ }
+}
diff --git a/models/dashboard.go b/models/dashboard.go
new file mode 100644
index 0000000..a9fb78b
--- /dev/null
+++ b/models/dashboard.go
@@ -0,0 +1,163 @@
+package models
+
+// Token represents a cryptocurrency token in the wallet
+type Token struct {
+ Symbol string
+ Name string
+ Balance string
+ Value string
+ Change string
+ Positive bool
+ Color string
+ Initials string
+ Network string
+}
+
+// Transaction represents a wallet transaction
+type Transaction struct {
+ Type string
+ Asset string
+ Amount string
+ USD string
+ Date string
+ Time string
+ Hash string
+ Positive bool
+ Address string
+}
+
+// NFT represents a non-fungible token in the wallet
+type NFT struct {
+ Name string
+ Collection string
+ Image string
+ Floor string
+ Value string
+ Badge string
+ Verified bool
+}
+
+type AreaSeriesData struct {
+ Date string `json:"date"`
+ Industry string `json:"industry"`
+ Value float64 `json:"value"`
+}
+
+type BubbleData struct {
+ Name string `json:"name"`
+ Sector string `json:"sector"`
+ Value float64 `json:"value"`
+}
+
+// DashboardData holds all data for the dashboard view
+type DashboardData struct {
+ TotalBalance string
+ Change24h string
+ Tokens []Token
+ Transactions []Transaction
+ NFTs []NFT
+ PortfolioChart []AreaSeriesData
+ MarketCapBubble []BubbleData
+}
+
+// DefaultTokens returns sample token data
+func DefaultTokens() []Token {
+ return []Token{
+ {Symbol: "SNR", Name: "Sonr", Balance: "8,432.50", Value: "$4,216.25", Change: "+5.67%", Positive: true, Color: "linear-gradient(135deg, #17c2ff, #0090ff)", Initials: "S", Network: "Sonr Mainnet"},
+ {Symbol: "ETH", Name: "Ethereum", Balance: "2.847", Value: "$6,682.04", Change: "+3.24%", Positive: true, Color: "#627eea", Initials: "E", Network: "Ethereum"},
+ {Symbol: "USDC", Name: "USD Coin", Balance: "1,250.00", Value: "$1,250.00", Change: "0.00%", Positive: true, Color: "#2775ca", Initials: "U", Network: "Ethereum"},
+ {Symbol: "AVAX", Name: "Avalanche", Balance: "24.83", Value: "$699.03", Change: "-2.18%", Positive: false, Color: "#e84142", Initials: "A", Network: "Avalanche"},
+ }
+}
+
+// DefaultTransactions returns sample transaction data
+func DefaultTransactions() []Transaction {
+ return []Transaction{
+ {Type: "receive", Asset: "ETH", Amount: "+0.25 ETH", USD: "$586.25", Date: "Today", Time: "2:34 PM", Hash: "0x8f4a2b1c...", Positive: true, Address: "0x742d...35Cb"},
+ {Type: "send", Asset: "SNR", Amount: "-500 SNR", USD: "$250.00", Date: "Yesterday", Time: "11:22 AM", Hash: "0x7d3e2a1b...", Positive: false, Address: "sonr1k4m...9p3q"},
+ {Type: "swap", Asset: "ETH -> USDC", Amount: "0.5 ETH", USD: "-> 1,172.50 USDC", Date: "Jan 1", Time: "9:15 AM", Hash: "0x1a2b3c4d...", Positive: true, Address: "Uniswap V3"},
+ }
+}
+
+// DefaultNFTs returns sample NFT data
+func DefaultNFTs() []NFT {
+ return []NFT{
+ {Name: "Bored Ape #4521", Collection: "Bored Ape Yacht Club", Image: "https://images.unsplash.com/photo-1620641788421-7a1c342ea42e?w=400&h=400&fit=crop", Floor: "28.5 ETH", Value: "32.0 ETH", Badge: "Listed", Verified: true},
+ {Name: "Sonr Genesis #001", Collection: "Sonr Genesis", Image: "https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=400&h=400&fit=crop", Floor: "0.8 ETH", Value: "2.5 ETH", Badge: "Rare", Verified: true},
+ }
+}
+
+// DefaultPortfolioChartData returns sample stacked area data for portfolio performance
+func DefaultPortfolioChartData() []AreaSeriesData {
+ return []AreaSeriesData{
+ // Day 1
+ {Date: "2024-12-25", Industry: "ETH", Value: 3200},
+ {Date: "2024-12-25", Industry: "SNR", Value: 2100},
+ {Date: "2024-12-25", Industry: "USDC", Value: 1200},
+ {Date: "2024-12-25", Industry: "AVAX", Value: 500},
+ // Day 2
+ {Date: "2024-12-26", Industry: "ETH", Value: 3350},
+ {Date: "2024-12-26", Industry: "SNR", Value: 2200},
+ {Date: "2024-12-26", Industry: "USDC", Value: 1200},
+ {Date: "2024-12-26", Industry: "AVAX", Value: 520},
+ // Day 3
+ {Date: "2024-12-27", Industry: "ETH", Value: 3500},
+ {Date: "2024-12-27", Industry: "SNR", Value: 2350},
+ {Date: "2024-12-27", Industry: "USDC", Value: 1200},
+ {Date: "2024-12-27", Industry: "AVAX", Value: 480},
+ // Day 4
+ {Date: "2024-12-28", Industry: "ETH", Value: 3280},
+ {Date: "2024-12-28", Industry: "SNR", Value: 2400},
+ {Date: "2024-12-28", Industry: "USDC", Value: 1200},
+ {Date: "2024-12-28", Industry: "AVAX", Value: 510},
+ // Day 5
+ {Date: "2024-12-29", Industry: "ETH", Value: 3450},
+ {Date: "2024-12-29", Industry: "SNR", Value: 2550},
+ {Date: "2024-12-29", Industry: "USDC", Value: 1250},
+ {Date: "2024-12-29", Industry: "AVAX", Value: 530},
+ // Day 6
+ {Date: "2024-12-30", Industry: "ETH", Value: 3600},
+ {Date: "2024-12-30", Industry: "SNR", Value: 2680},
+ {Date: "2024-12-30", Industry: "USDC", Value: 1250},
+ {Date: "2024-12-30", Industry: "AVAX", Value: 550},
+ // Day 7
+ {Date: "2024-12-31", Industry: "ETH", Value: 3750},
+ {Date: "2024-12-31", Industry: "SNR", Value: 2800},
+ {Date: "2024-12-31", Industry: "USDC", Value: 1250},
+ {Date: "2024-12-31", Industry: "AVAX", Value: 580},
+ // Day 8
+ {Date: "2025-01-01", Industry: "ETH", Value: 3680},
+ {Date: "2025-01-01", Industry: "SNR", Value: 2900},
+ {Date: "2025-01-01", Industry: "USDC", Value: 1250},
+ {Date: "2025-01-01", Industry: "AVAX", Value: 600},
+ }
+}
+
+// DefaultMarketCapBubbleData returns sample bubble chart data for market cap dominance
+func DefaultMarketCapBubbleData() []BubbleData {
+ return []BubbleData{
+ {Name: "BTC", Sector: "Layer 1", Value: 45000},
+ {Name: "ETH", Sector: "Layer 1", Value: 28000},
+ {Name: "SNR", Sector: "Layer 1", Value: 8500},
+ {Name: "SOL", Sector: "Layer 1", Value: 12000},
+ {Name: "AVAX", Sector: "Layer 1", Value: 6000},
+ {Name: "USDC", Sector: "Stablecoin", Value: 15000},
+ {Name: "USDT", Sector: "Stablecoin", Value: 18000},
+ {Name: "UNI", Sector: "DeFi", Value: 4500},
+ {Name: "AAVE", Sector: "DeFi", Value: 3200},
+ {Name: "LINK", Sector: "Oracle", Value: 5800},
+ }
+}
+
+// DefaultDashboardData returns a complete dashboard data set with sample data
+func DefaultDashboardData() DashboardData {
+ return DashboardData{
+ TotalBalance: "12847.32",
+ Change24h: "+$302.18",
+ Tokens: DefaultTokens(),
+ Transactions: DefaultTransactions(),
+ NFTs: DefaultNFTs(),
+ PortfolioChart: DefaultPortfolioChartData(),
+ MarketCapBubble: DefaultMarketCapBubbleData(),
+ }
+}
diff --git a/models/login.go b/models/login.go
new file mode 100644
index 0000000..b8b535b
--- /dev/null
+++ b/models/login.go
@@ -0,0 +1,15 @@
+package models
+
+// LoginState holds the current login flow state
+type LoginState struct {
+ Step string
+ Method string
+ Error string
+}
+
+// DefaultLoginState returns a new login state at step 1
+func DefaultLoginState() LoginState {
+ return LoginState{
+ Step: "1",
+ }
+}
diff --git a/models/register.go b/models/register.go
new file mode 100644
index 0000000..b3e37d2
--- /dev/null
+++ b/models/register.go
@@ -0,0 +1,32 @@
+package models
+
+// DeviceCapabilities holds WebAuthn capability detection results
+type DeviceCapabilities struct {
+ Platform bool // Biometrics (Face ID, Touch ID, Windows Hello)
+ CrossPlatform bool // Security keys (YubiKey, etc.)
+ Conditional bool // Passkey autofill support
+}
+
+// RegisterState holds the current registration flow state
+type RegisterState struct {
+ Step int
+ Method string // "passkey", "security-key", or "qr-code"
+ Username string
+ Error string
+}
+
+// DefaultRegisterState returns a new registration state at step 1
+func DefaultRegisterState() RegisterState {
+ return RegisterState{
+ Step: 1,
+ }
+}
+
+// DefaultDeviceCapabilities returns capabilities assuming full support (for testing)
+func DefaultDeviceCapabilities() DeviceCapabilities {
+ return DeviceCapabilities{
+ Platform: true,
+ CrossPlatform: true,
+ Conditional: true,
+ }
+}
diff --git a/models/settings.go b/models/settings.go
new file mode 100644
index 0000000..e481bc4
--- /dev/null
+++ b/models/settings.go
@@ -0,0 +1,225 @@
+package models
+
+import "time"
+
+type SocialLinks struct {
+ Twitter string
+ GitHub string
+ Discord string
+}
+
+type ProfileSettings struct {
+ AvatarURL string
+ Initials string
+ DisplayName string
+ Username string
+ Bio string
+ Website string
+ SocialLinks SocialLinks
+ Visibility string
+}
+
+type Device struct {
+ ID string
+ Name string
+ Type string
+ Browser string
+ OS string
+ AuthType string
+ AddedAt time.Time
+ LastUsed time.Time
+ IsCurrent bool
+}
+
+type OAuthScope struct {
+ Name string
+ Description string
+ Enabled bool
+ Required bool
+}
+
+type AuthorizedClient struct {
+ ID string
+ Name string
+ Domain string
+ Initials string
+ Color string
+ Status string
+}
+
+type OAuthSettings struct {
+ DefaultScopes []OAuthScope
+ SessionDuration string
+ ConsentPrompt string
+ Clients []AuthorizedClient
+}
+
+type NotificationItem struct {
+ Key string
+ Title string
+ Description string
+ Enabled bool
+ Threshold int
+}
+
+type NotificationPrefs struct {
+ SecurityAlerts []NotificationItem
+ Transactions []NotificationItem
+ Apps []NotificationItem
+ Marketing []NotificationItem
+}
+
+type Email struct {
+ ID string
+ Address string
+ IsPrimary bool
+ IsVerified bool
+ AddedAt time.Time
+}
+
+type Phone struct {
+ ID string
+ Number string
+ IsPrimary bool
+ IsVerified bool
+ AddedAt time.Time
+ Use2FA bool
+}
+
+type SMSSettings struct {
+ Enabled bool
+ RecoveryCodes bool
+}
+
+type APIKey struct {
+ ID string
+ Name string
+ KeyPreview string
+ KeyFull string
+ Environment string
+ Permissions string
+ Status string
+ CreatedAt time.Time
+}
+
+type Webhook struct {
+ ID string
+ URL string
+ Description string
+ Events []string
+ Status string
+ LastTriggered time.Time
+ FailureCount int
+}
+
+type OAuthAppConfig struct {
+ ClientID string
+ ClientSecret string
+ RedirectURIs []string
+}
+
+type DeveloperSettings struct {
+ APIKeys []APIKey
+ Webhooks []Webhook
+ OAuthApp OAuthAppConfig
+ DebugMode bool
+ TestMode bool
+ ShowRaw bool
+}
+
+type SettingsData struct {
+ Profile ProfileSettings
+ Devices []Device
+ OAuth OAuthSettings
+ Notifications NotificationPrefs
+ Emails []Email
+ Phones []Phone
+ SMSSettings SMSSettings
+ Developer DeveloperSettings
+}
+
+func DefaultSettingsData() SettingsData {
+ return SettingsData{
+ Profile: ProfileSettings{
+ Initials: "JD",
+ DisplayName: "John Doe",
+ Username: "johndoe",
+ Bio: "Web3 enthusiast and DeFi explorer. Building on Sonr.",
+ Website: "https://johndoe.dev",
+ Visibility: "public",
+ },
+ Devices: []Device{
+ {ID: "dev-1", Name: "MacBook Pro", Type: "laptop", Browser: "Chrome", OS: "macOS", AuthType: "Touch ID", AddedAt: time.Now().AddDate(0, 0, -20), LastUsed: time.Now(), IsCurrent: true},
+ {ID: "dev-2", Name: "iPhone 15 Pro", Type: "mobile", Browser: "Safari", OS: "iOS", AuthType: "Face ID", AddedAt: time.Now().AddDate(0, 0, -25), LastUsed: time.Now().Add(-2 * time.Hour), IsCurrent: false},
+ {ID: "dev-3", Name: "YubiKey 5C", Type: "key", Browser: "", OS: "", AuthType: "FIDO2", AddedAt: time.Now().AddDate(0, -1, -7), LastUsed: time.Now().AddDate(0, 0, -5), IsCurrent: false},
+ {ID: "dev-4", Name: "Windows Desktop", Type: "desktop", Browser: "Firefox", OS: "Windows", AuthType: "Windows Hello", AddedAt: time.Now().AddDate(0, -2, 0), LastUsed: time.Now().AddDate(0, 0, -14), IsCurrent: false},
+ },
+ OAuth: OAuthSettings{
+ DefaultScopes: []OAuthScope{
+ {Name: "openid", Description: "Basic identity information (required)", Enabled: true, Required: true},
+ {Name: "profile", Description: "Display name and avatar", Enabled: true, Required: false},
+ {Name: "email", Description: "Email address access", Enabled: false, Required: false},
+ {Name: "wallet:read", Description: "View wallet balances", Enabled: false, Required: false},
+ },
+ SessionDuration: "7d",
+ ConsentPrompt: "first",
+ Clients: []AuthorizedClient{
+ {ID: "client-1", Name: "Uniswap", Domain: "app.uniswap.org", Initials: "U", Color: "linear-gradient(135deg, #ff007a, #ff5ca0)", Status: "active"},
+ {ID: "client-2", Name: "OpenSea", Domain: "opensea.io", Initials: "O", Color: "linear-gradient(135deg, #627eea, #4c63d2)", Status: "idle"},
+ },
+ },
+ Notifications: NotificationPrefs{
+ SecurityAlerts: []NotificationItem{
+ {Key: "security.new_device", Title: "New device login", Description: "When your account is accessed from a new device", Enabled: true},
+ {Key: "security.suspicious", Title: "Suspicious activity", Description: "Unusual login attempts or access patterns", Enabled: true},
+ {Key: "security.password", Title: "Password changes", Description: "When security credentials are modified", Enabled: true},
+ },
+ Transactions: []NotificationItem{
+ {Key: "tx.incoming", Title: "Incoming transfers", Description: "When you receive tokens or NFTs", Enabled: true},
+ {Key: "tx.outgoing", Title: "Outgoing transfers", Description: "Confirmation of sent transactions", Enabled: true},
+ {Key: "tx.failed", Title: "Failed transactions", Description: "When a transaction fails or is reverted", Enabled: true},
+ {Key: "tx.large", Title: "Large transactions", Description: "Transactions above threshold", Enabled: true, Threshold: 1000},
+ },
+ Apps: []NotificationItem{
+ {Key: "app.connection", Title: "New app connections", Description: "When a new app connects to your wallet", Enabled: true},
+ {Key: "app.signature", Title: "Signature requests", Description: "When an app requests a signature", Enabled: true},
+ {Key: "app.permission", Title: "Permission changes", Description: "When app permissions are modified", Enabled: false},
+ },
+ Marketing: []NotificationItem{
+ {Key: "marketing.updates", Title: "Product updates", Description: "New features and improvements", Enabled: false},
+ {Key: "marketing.newsletter", Title: "Newsletter", Description: "Weekly digest of Sonr ecosystem news", Enabled: false},
+ },
+ },
+ Emails: []Email{
+ {ID: "email-1", Address: "john.doe@example.com", IsPrimary: true, IsVerified: true, AddedAt: time.Now().AddDate(0, 0, -20)},
+ {ID: "email-2", Address: "johndoe.work@company.io", IsPrimary: false, IsVerified: true, AddedAt: time.Now().AddDate(0, -1, -15)},
+ {ID: "email-3", Address: "backup@gmail.com", IsPrimary: false, IsVerified: false, AddedAt: time.Now().AddDate(0, 0, -2)},
+ },
+ Phones: []Phone{
+ {ID: "phone-1", Number: "+1 (555) 123-4567", IsPrimary: true, IsVerified: true, AddedAt: time.Now().AddDate(0, 0, -20), Use2FA: true},
+ {ID: "phone-2", Number: "+44 7700 900123", IsPrimary: false, IsVerified: true, AddedAt: time.Now().AddDate(0, -2, -10), Use2FA: false},
+ },
+ SMSSettings: SMSSettings{
+ Enabled: true,
+ RecoveryCodes: false,
+ },
+ Developer: DeveloperSettings{
+ APIKeys: []APIKey{
+ {ID: "key-1", Name: "Production Key", KeyPreview: "sk_live_••••••••••••••••••••••••3f8b", KeyFull: "sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f23f8b", Environment: "live", Permissions: "full", Status: "active", CreatedAt: time.Now().AddDate(0, 0, -35)},
+ {ID: "key-2", Name: "Test Key", KeyPreview: "sk_test_••••••••••••••••••••••••9a2c", KeyFull: "sk_test_z9y8x7w6v5u4t3s2r1q0p9o8n7m6l5k4j3i2h1g0f9e8d7c6b5a4z3y2x1w0v9u89a2c", Environment: "test", Permissions: "full", Status: "active", CreatedAt: time.Now().AddDate(0, 0, -35)},
+ },
+ Webhooks: []Webhook{
+ {ID: "wh-1", URL: "https://api.myapp.com/webhooks/sonr", Description: "Main webhook", Events: []string{"*"}, Status: "active", LastTriggered: time.Now().Add(-2 * time.Hour), FailureCount: 0},
+ {ID: "wh-2", URL: "https://hooks.slack.com/services/...", Description: "Slack notifications", Events: []string{"transaction.*"}, Status: "failing", LastTriggered: time.Now().Add(-1 * time.Hour), FailureCount: 3},
+ },
+ OAuthApp: OAuthAppConfig{
+ ClientID: "sonr_client_a1b2c3d4e5f6",
+ ClientSecret: "sonr_secret_x9y8z7w6v5u4t3s2r1",
+ RedirectURIs: []string{"https://myapp.com/auth/callback", "http://localhost:3000/auth/callback"},
+ },
+ DebugMode: false,
+ TestMode: true,
+ ShowRaw: false,
+ },
+ }
+}
diff --git a/views/settings.templ b/views/settings.templ
new file mode 100644
index 0000000..839d1fa
--- /dev/null
+++ b/views/settings.templ
@@ -0,0 +1,1142 @@
+package views
+
+import (
+ "nebula/layouts"
+ "nebula/models"
+ "strconv"
+ "strings"
+ "time"
+)
+
+templ SettingsPage(data models.SettingsData, activeTab string) {
+ @layouts.DashboardLayout("Settings - Sonr", layouts.WalletUser{Name: "Sonr Wallet", Address: "sonr1x9f...7k2m"}, "settings") {
+ @settingsStyles()
+
+
+
+
+
+ Profile
+
+
+
+ Devices
+
+
+
+ OAuth
+
+
+
+ Notifications
+
+
+
+ Emails
+
+
+
+ Phone Numbers
+
+
+
+ Developer
+
+
+ @ProfileTab(data.Profile)
+
+
+ @DevicesTab(data.Devices)
+
+
+ @OAuthTab(data.OAuth)
+
+
+ @NotificationsTab(data.Notifications)
+
+
+ @EmailsTab(data.Emails)
+
+
+ @PhonesTab(data.Phones, data.SMSSettings)
+
+
+ @DeveloperTab(data.Developer)
+
+
+
+ @AddEmailDialog()
+ @AddPhoneDialog()
+ @AddDeviceDialog()
+ @GenerateKeyDialog()
+ @AddWebhookDialog()
+ @settingsScripts()
+ }
+}
+
+templ ProfileTab(profile models.ProfileSettings) {
+
+
+
+
+
+
+
+
+
+ Cancel
+ Save Changes
+
+
+}
+
+templ DevicesTab(devices []models.Device) {
+
+
+
+ Linked Devices
+ Passkeys and security keys registered with your account
+
+
+
+ Add Device
+
+
+
+ for _, device := range devices {
+ @DeviceItem(device)
+ }
+
+
+
+
+ Security Recommendation
+ Register at least 2 devices to ensure account recovery if one is lost.
+
+
+
+}
+
+templ DeviceItem(device models.Device) {
+
+
+
+
+
+
+
+ { device.Name }
+ if device.IsCurrent {
+ Current
+ }
+
+
+ if device.Browser != "" {
+ { device.Browser } on { device.OS } -
+ }
+ { device.AuthType }
+
+
+
+
+ Added { formatDate(device.AddedAt) }
+ Last used: { formatRelativeTime(device.LastUsed) }
+
+
+
+
+
+ Rename
+
+
+
+
+ Remove
+
+
+
+}
+
+func deviceIcon(deviceType string) string {
+ switch deviceType {
+ case "laptop":
+ return "laptop"
+ case "mobile":
+ return "mobile"
+ case "key":
+ return "key"
+ case "desktop":
+ return "desktop"
+ default:
+ return "laptop"
+ }
+}
+
+templ OAuthTab(oauth models.OAuthSettings) {
+
+
+
+ OAuth Settings
+ Configure your identity provider settings
+
+
+
+
+
+
+
+
+ Authorized Clients
+ View All
+
+
+ for _, client := range oauth.Clients {
+ @AuthorizedClientCard(client)
+ }
+
+
+
+ Cancel
+ Save Changes
+
+
+}
+
+templ AuthorizedClientCard(client models.AuthorizedClient) {
+
+
+
+
+
+ { client.Name }
+ { client.Domain }
+
+
+
+ if client.Status == "active" {
+ Active
+ } else {
+ Idle
+ }
+ Revoke
+
+
+
+}
+
+templ NotificationsTab(prefs models.NotificationPrefs) {
+
+
+ Notification Preferences
+ Choose how and when you receive notifications
+
+
+ Security Alerts
+
+ for _, item := range prefs.SecurityAlerts {
+ @NotificationRow(item)
+ }
+
+
+
+ Transaction Notifications
+
+ for _, item := range prefs.Transactions {
+ @NotificationRow(item)
+ }
+
+
+
+ App Notifications
+
+ for _, item := range prefs.Apps {
+ @NotificationRow(item)
+ }
+
+
+
+ Marketing & Updates
+
+ for _, item := range prefs.Marketing {
+ @NotificationRow(item)
+ }
+
+
+
+ Save Preferences
+
+
+}
+
+templ NotificationRow(item models.NotificationItem) {
+
+
+ { item.Title }
+ { item.Description }
+
+ if item.Threshold > 0 {
+
+
+ USD
+
+
+
+ } else {
+
+ }
+
+}
+
+templ EmailsTab(emails []models.Email) {
+
+
+
+ Email Addresses
+ Manage email addresses linked to your account
+
+
+
+ Add Email
+
+
+
+ for _, email := range emails {
+ @EmailItem(email)
+ }
+
+
+
+ Your primary email is used for account recovery and important notifications. You must have at least one verified email.
+
+
+}
+
+templ EmailItem(email models.Email) {
+
+}
+
+templ PhonesTab(phones []models.Phone, smsSettings models.SMSSettings) {
+
+
+
+ Phone Numbers
+ Manage phone numbers for 2FA and recovery
+
+
+
+ Add Phone
+
+
+
+ for _, phone := range phones {
+ @PhoneItem(phone)
+ }
+
+
+ SMS Authentication
+
+
+
+ Enable SMS 2FA
+ Receive codes via SMS for high-risk actions
+
+
+
+
+
+ SMS recovery codes
+ Allow account recovery via SMS
+
+
+
+
+
+
+
+
+ SMS Security Notice
+ SMS-based authentication is less secure than passkeys. We recommend using passkeys as your primary authentication method.
+
+
+
+}
+
+templ PhoneItem(phone models.Phone) {
+
+}
+
+templ DeveloperTab(dev models.DeveloperSettings) {
+
+
+ Developer Settings
+ API access and integration options
+
+
+
+ API Keys
+
+
+ Generate Key
+
+
+
+ for _, key := range dev.APIKeys {
+ @APIKeyCard(key)
+ }
+
+
+
+
+ Webhooks
+
+
+ Add Endpoint
+
+
+
+ for _, wh := range dev.Webhooks {
+ @WebhookCard(wh)
+ }
+
+
+ @OAuthAppConfigCard(dev.OAuthApp)
+
+ Developer Mode
+
+
+
+ Enable debug logging
+ Log detailed API requests and responses
+
+
+
+
+
+ Test mode
+ Use testnet for all transactions
+
+
+
+
+
+ Show raw responses
+ Display JSON in UI for debugging
+
+
+
+
+
+
+
+
+
+
+ Cancel
+ Save Changes
+
+
+}
+
+templ APIKeyCard(key models.APIKey) {
+
+
+
+ { key.Name }
+ Created { formatDate(key.CreatedAt) }
+
+ if key.Environment == "live" {
+
Active
+ } else {
+
Test Mode
+ }
+
+
+ { key.KeyPreview }
+
+
+
+
+
+
+}
+
+templ WebhookCard(wh models.Webhook) {
+
+
+
+
+ { wh.URL }
+ if wh.Status == "active" {
+ Active
+ } else {
+ Failing
+ }
+
+ if wh.Status == "failing" {
+
{ formatEvents(wh.Events) } events - { itoa(wh.FailureCount) } failures in last hour
+ } else {
+
{ formatEvents(wh.Events) } events - Last triggered { formatRelativeTime(wh.LastTriggered) }
+ }
+
+
+
+
+
+ Edit
+
+
+
+ Send Test
+
+
+
+ View Logs
+
+
+
+
+ Delete
+
+
+
+
+}
+
+templ OAuthAppConfigCard(config models.OAuthAppConfig) {
+
+ OAuth Application
+
+
+
+
+
+ Redirect URIs
+ for _, uri := range config.RedirectURIs {
+
+
+
+ }
+
+
+ Add URI
+
+
+
+
+}
+
+templ AddEmailDialog() {
+
+
+
+
+
+
+
+ We'll send a verification link to this address.
+
+
+
+ Cancel
+ Send Verification
+
+
+}
+
+templ AddPhoneDialog() {
+
+
+
+
+ +1
+ +44
+ +49
+ +33
+ +81
+
+
+
+
+
+
+
+ We'll send a verification code via SMS.
+
+
+
+ Cancel
+ Send Code
+
+
+}
+
+templ AddDeviceDialog() {
+
+
+
+
+ Register a Passkey
+
+ Use your device's built-in authenticator (Face ID, Touch ID, Windows Hello) or a security key.
+
+
+
+
+ Register Device
+
+
or
+
+
+ Use Security Key
+
+
+
+ Cancel
+
+
+}
+
+templ GenerateKeyDialog() {
+
+
+
+
+
+
+ Test Mode
+ Production
+
+
+ Full Access
+ Read Only
+ Write Only
+
+
+
+ Your secret key will only be shown once. Store it securely.
+
+
+
+ Cancel
+ Generate Key
+
+
+}
+
+templ AddWebhookDialog() {
+
+
+
+
+
+
+
+
+
+
Events to Subscribe
+
+
+ transaction.*
+ All transaction events
+
+
+
+
+ connection.*
+ App connection events
+
+
+
+
+ signature.*
+ Signature request events
+
+
+
+
+ account.*
+ Account update events
+
+
+
+
+
+ Cancel
+ Create Webhook
+
+
+}
+
+func itoa(i int) string {
+ return strconv.Itoa(i)
+}
+
+func formatDate(t time.Time) string {
+ return t.Format("Jan 2, 2006")
+}
+
+func formatRelativeTime(t time.Time) string {
+ diff := time.Since(t)
+ if diff < time.Minute {
+ return "Just now"
+ }
+ if diff < time.Hour {
+ mins := int(diff.Minutes())
+ if mins == 1 {
+ return "1 minute ago"
+ }
+ return strconv.Itoa(mins) + " minutes ago"
+ }
+ if diff < 24*time.Hour {
+ hours := int(diff.Hours())
+ if hours == 1 {
+ return "1 hour ago"
+ }
+ return strconv.Itoa(hours) + " hours ago"
+ }
+ days := int(diff.Hours() / 24)
+ if days == 1 {
+ return "1 day ago"
+ }
+ if days < 14 {
+ return strconv.Itoa(days) + " days ago"
+ }
+ weeks := days / 7
+ if weeks == 1 {
+ return "1 week ago"
+ }
+ return strconv.Itoa(weeks) + " weeks ago"
+}
+
+func formatEvents(events []string) string {
+ if len(events) == 1 && events[0] == "*" {
+ return "All"
+ }
+ return strings.Join(events, ", ")
+}
+
+templ settingsStyles() {
+
+}
+
+templ settingsScripts() {
+
+}
diff --git a/views/settings_templ.go b/views/settings_templ.go
new file mode 100644
index 0000000..d4589bb
--- /dev/null
+++ b/views/settings_templ.go
@@ -0,0 +1,2152 @@
+// Code generated by templ - DO NOT EDIT.
+
+// templ: version: v0.3.977
+package views
+
+//lint:file-ignore SA4006 This context is only used if a nested component is present.
+
+import "github.com/a-h/templ"
+import templruntime "github.com/a-h/templ/runtime"
+
+import (
+ "nebula/layouts"
+ "nebula/models"
+ "strconv"
+ "strings"
+ "time"
+)
+
+func SettingsPage(data models.SettingsData, activeTab string) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var1 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var1 == nil {
+ templ_7745c5c3_Var1 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Err = settingsStyles().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " Profile Devices OAuth Notifications Emails Phone Numbers Developer ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = ProfileTab(data.Profile).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = DevicesTab(data.Devices).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = OAuthTab(data.OAuth).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = NotificationsTab(data.Notifications).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = EmailsTab(data.Emails).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = PhonesTab(data.Phones, data.SMSSettings).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = DeveloperTab(data.Developer).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = AddEmailDialog().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = AddPhoneDialog().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = AddDeviceDialog().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = GenerateKeyDialog().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = AddWebhookDialog().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = settingsScripts().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+ templ_7745c5c3_Err = layouts.DashboardLayout("Settings - Sonr", layouts.WalletUser{Name: "Sonr Wallet", Address: "sonr1x9f...7k2m"}, "settings").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func ProfileTab(profile models.ProfileSettings) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var3 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var3 == nil {
+ templ_7745c5c3_Var3 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func DevicesTab(devices []models.Device) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var14 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var14 == nil {
+ templ_7745c5c3_Var14 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "Linked Devices Passkeys and security keys registered with your account
Add Device")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, device := range devices {
+ templ_7745c5c3_Err = DeviceItem(device).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "
Security Recommendation Register at least 2 devices to ensure account recovery if one is lost.
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func DeviceItem(device models.Device) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var15 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var15 == nil {
+ templ_7745c5c3_Var15 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var18 string
+ templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(device.Name)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 234, Col: 45}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if device.IsCurrent {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "Current")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if device.Browser != "" {
+ var templ_7745c5c3_Var19 string
+ templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(device.Browser)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 241, Col: 22}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, " on ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var20 string
+ templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(device.OS)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 241, Col: 39}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, " - ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ var templ_7745c5c3_Var21 string
+ templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(device.AuthType)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 243, Col: 22}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "Added ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var22 string
+ templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(formatDate(device.AddedAt))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 248, Col: 64}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, " Last used: ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var23 string
+ templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(formatRelativeTime(device.LastUsed))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 249, Col: 123}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "
Rename Remove ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func deviceIcon(deviceType string) string {
+ switch deviceType {
+ case "laptop":
+ return "laptop"
+ case "mobile":
+ return "mobile"
+ case "key":
+ return "key"
+ case "desktop":
+ return "desktop"
+ default:
+ return "laptop"
+ }
+}
+
+func OAuthTab(oauth models.OAuthSettings) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var26 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var26 == nil {
+ templ_7745c5c3_Var26 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "OAuth Settings Configure your identity provider settings
Authorized Clients View All
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, client := range oauth.Clients {
+ templ_7745c5c3_Err = AuthorizedClientCard(client).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "
Cancel Save Changes
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func AuthorizedClientCard(client models.AuthorizedClient) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var31 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var31 == nil {
+ templ_7745c5c3_Var31 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var34 string
+ templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(client.Name)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 366, Col: 45}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var35 string
+ templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(client.Domain)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 367, Col: 92}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if client.Status == "active" {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "Active ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "Idle ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "Revoke
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func NotificationsTab(prefs models.NotificationPrefs) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var37 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var37 == nil {
+ templ_7745c5c3_Var37 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 74, "Notification Preferences Choose how and when you receive notifications
Security Alerts")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, item := range prefs.SecurityAlerts {
+ templ_7745c5c3_Err = NotificationRow(item).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "
Transaction Notifications")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, item := range prefs.Transactions {
+ templ_7745c5c3_Err = NotificationRow(item).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, "
App Notifications")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, item := range prefs.Apps {
+ templ_7745c5c3_Err = NotificationRow(item).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 77, "
Marketing & Updates")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, item := range prefs.Marketing {
+ templ_7745c5c3_Err = NotificationRow(item).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "
Save Preferences
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func NotificationRow(item models.NotificationItem) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var38 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var38 == nil {
+ templ_7745c5c3_Var38 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var39 string
+ templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 429, Col: 43}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var39))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var40 string
+ templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinStringErrs(item.Description)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 430, Col: 92}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if item.Threshold > 0 {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "
USD
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 87, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 91, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func EmailsTab(emails []models.Email) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var44 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var44 == nil {
+ templ_7745c5c3_Var44 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 92, "Email Addresses Manage email addresses linked to your account
Add Email")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, email := range emails {
+ templ_7745c5c3_Err = EmailItem(email).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 93, "
Your primary email is used for account recovery and important notifications. You must have at least one verified email. ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func EmailItem(email models.Email) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var45 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var45 == nil {
+ templ_7745c5c3_Var45 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 94, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func PhonesTab(phones []models.Phone, smsSettings models.SMSSettings) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var52 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var52 == nil {
+ templ_7745c5c3_Var52 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 115, "Phone Numbers Manage phone numbers for 2FA and recovery
Add Phone")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, phone := range phones {
+ templ_7745c5c3_Err = PhoneItem(phone).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 116, "
SMS AuthenticationEnable SMS 2FA Receive codes via SMS for high-risk actions
SMS recovery codes Allow account recovery via SMS
SMS Security Notice SMS-based authentication is less secure than passkeys. We recommend using passkeys as your primary authentication method.
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func PhoneItem(phone models.Phone) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var53 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var53 == nil {
+ templ_7745c5c3_Var53 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 121, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func DeveloperTab(dev models.DeveloperSettings) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var60 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var60 == nil {
+ templ_7745c5c3_Var60 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 137, "Developer Settings API access and integration options
API Keys Generate Key
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, key := range dev.APIKeys {
+ templ_7745c5c3_Err = APIKeyCard(key).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 138, "
Webhooks Add Endpoint
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, wh := range dev.Webhooks {
+ templ_7745c5c3_Err = WebhookCard(wh).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 139, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = OAuthAppConfigCard(dev.OAuthApp).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 140, "
Developer ModeEnable debug logging Log detailed API requests and responses
Test mode Use testnet for all transactions
Show raw responses Display JSON in UI for debugging
Cancel Save Changes
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func APIKeyCard(key models.APIKey) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var61 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var61 == nil {
+ templ_7745c5c3_Var61 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 147, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var62 string
+ templ_7745c5c3_Var62, templ_7745c5c3_Err = templ.JoinStringErrs(key.Name)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 692, Col: 42}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var62))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 148, " Created ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var63 string
+ templ_7745c5c3_Var63, templ_7745c5c3_Err = templ.JoinStringErrs(formatDate(key.CreatedAt))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 693, Col: 111}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var63))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 149, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if key.Environment == "live" {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 150, "
Active")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 151, "
Test Mode")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 152, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var64 string
+ templ_7745c5c3_Var64, templ_7745c5c3_Err = templ.JoinStringErrs(key.KeyPreview)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 702, Col: 25}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var64))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 153, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func WebhookCard(wh models.Webhook) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var66 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var66 == nil {
+ templ_7745c5c3_Var66 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 155, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var67 string
+ templ_7745c5c3_Var67, templ_7745c5c3_Err = templ.JoinStringErrs(wh.URL)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 716, Col: 41}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var67))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 156, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if wh.Status == "active" {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 157, "Active")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 158, "Failing")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 159, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ if wh.Status == "failing" {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 160, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var68 string
+ templ_7745c5c3_Var68, templ_7745c5c3_Err = templ.JoinStringErrs(formatEvents(wh.Events))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 724, Col: 97}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var68))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 161, " events - ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var69 string
+ templ_7745c5c3_Var69, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(wh.FailureCount))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 724, Col: 132}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var69))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 162, " failures in last hour")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ } else {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 163, "
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var70 string
+ templ_7745c5c3_Var70, templ_7745c5c3_Err = templ.JoinStringErrs(formatEvents(wh.Events))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 726, Col: 102}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var70))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 164, " events - Last triggered ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var71 string
+ templ_7745c5c3_Var71, templ_7745c5c3_Err = templ.JoinStringErrs(formatRelativeTime(wh.LastTriggered))
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/settings.templ`, Line: 726, Col: 167}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var71))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 165, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 166, "
Edit Send Test View Logs Delete ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func OAuthAppConfigCard(config models.OAuthAppConfig) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var74 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var74 == nil {
+ templ_7745c5c3_Var74 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 169, "OAuth ApplicationRedirect URIs ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, uri := range config.RedirectURIs {
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 173, " ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 175, " Add URI
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func AddEmailDialog() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var79 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var79 == nil {
+ templ_7745c5c3_Var79 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 176, " We'll send a verification link to this address.
Cancel Send Verification
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func AddPhoneDialog() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var80 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var80 == nil {
+ templ_7745c5c3_Var80 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 177, "+1 +44 +49 +33 +81
We'll send a verification code via SMS.Cancel Send Code
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func AddDeviceDialog() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var81 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var81 == nil {
+ templ_7745c5c3_Var81 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 178, "Register a Passkey Use your device's built-in authenticator (Face ID, Touch ID, Windows Hello) or a security key.
Register Device or Use Security KeyCancel
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func GenerateKeyDialog() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var82 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var82 == nil {
+ templ_7745c5c3_Var82 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 179, " Test Mode Production Full Access Read Only Write Only Your secret key will only be shown once. Store it securely.
Cancel Generate Key
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func AddWebhookDialog() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var83 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var83 == nil {
+ templ_7745c5c3_Var83 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 180, " Events to Subscribe transaction.* All transaction events
connection.* App connection events
signature.* Signature request events
account.* Account update events
Cancel Create Webhook
")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func itoa(i int) string {
+ return strconv.Itoa(i)
+}
+
+func formatDate(t time.Time) string {
+ return t.Format("Jan 2, 2006")
+}
+
+func formatRelativeTime(t time.Time) string {
+ diff := time.Since(t)
+ if diff < time.Minute {
+ return "Just now"
+ }
+ if diff < time.Hour {
+ mins := int(diff.Minutes())
+ if mins == 1 {
+ return "1 minute ago"
+ }
+ return strconv.Itoa(mins) + " minutes ago"
+ }
+ if diff < 24*time.Hour {
+ hours := int(diff.Hours())
+ if hours == 1 {
+ return "1 hour ago"
+ }
+ return strconv.Itoa(hours) + " hours ago"
+ }
+ days := int(diff.Hours() / 24)
+ if days == 1 {
+ return "1 day ago"
+ }
+ if days < 14 {
+ return strconv.Itoa(days) + " days ago"
+ }
+ weeks := days / 7
+ if weeks == 1 {
+ return "1 week ago"
+ }
+ return strconv.Itoa(weeks) + " weeks ago"
+}
+
+func formatEvents(events []string) string {
+ if len(events) == 1 && events[0] == "*" {
+ return "All"
+ }
+ return strings.Join(events, ", ")
+}
+
+func settingsStyles() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var84 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var84 == nil {
+ templ_7745c5c3_Var84 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 181, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+func settingsScripts() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var85 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var85 == nil {
+ templ_7745c5c3_Var85 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 182, "")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return nil
+ })
+}
+
+var _ = templruntime.GeneratedTemplate