diff --git a/src/components/PWASettings.tsx b/src/components/PWASettings.tsx index c44c601..aa656b1 100644 --- a/src/components/PWASettings.tsx +++ b/src/components/PWASettings.tsx @@ -1,39 +1,31 @@ -import { Card } from '@/components/ui/card' -import { Button } from '@/components/ui/button' -import { Label } from '@/components/ui/label' -import { Switch } from '@/components/ui/switch' -import { Separator } from '@/components/ui/separator' import { Badge } from '@/components/ui/badge' +import { Card } from '@/components/ui/card' +import { Label } from '@/components/ui/label' +import pwaSettingsCopy from '@/data/pwa-settings.json' import { usePWA } from '@/hooks/use-pwa' -import { useState, useEffect } from 'react' -import { - Download, - CloudArrowDown, - Trash, - Bell, - WifiSlash, - WifiHigh, - CheckCircle, - XCircle, - Question -} from '@phosphor-icons/react' +import { useEffect, useState } from 'react' +import { CheckCircle, WifiHigh, WifiSlash, XCircle } from '@phosphor-icons/react' import { toast } from 'sonner' +import { CacheSection } from './pwa-settings/CacheSection' +import { InstallSection } from './pwa-settings/InstallSection' +import { NotificationsSection } from './pwa-settings/NotificationsSection' +import { UpdateSection } from './pwa-settings/UpdateSection' export function PWASettings() { - const { - isInstalled, - isInstallable, - isOnline, + const { + isInstalled, + isInstallable, + isOnline, isUpdateAvailable, - installApp, - updateApp, + installApp, + updateApp, clearCache, requestNotificationPermission, registration } = usePWA() - + const [notificationPermission, setNotificationPermission] = useState('default') - const [cacheSize, setCacheSize] = useState('Calculating...') + const [cacheSize, setCacheSize] = useState(pwaSettingsCopy.defaults.cacheCalculating) useEffect(() => { if ('Notification' in window) { @@ -41,9 +33,9 @@ export function PWASettings() { } if ('storage' in navigator && 'estimate' in navigator.storage) { - navigator.storage.estimate().then(estimate => { + navigator.storage.estimate().then((estimate) => { const usageInMB = ((estimate.usage || 0) / (1024 * 1024)).toFixed(2) - setCacheSize(`${usageInMB} MB`) + setCacheSize(`${usageInMB} ${pwaSettingsCopy.cache.storageUnit}`) }) } }, []) @@ -51,99 +43,55 @@ export function PWASettings() { const handleInstall = async () => { const success = await installApp() if (success) { - toast.success('App installed successfully!') + toast.success(pwaSettingsCopy.toasts.installSuccess) } else { - toast.error('Installation cancelled') + toast.error(pwaSettingsCopy.toasts.installCancelled) } } const handleUpdate = () => { updateApp() - toast.info('Updating app...') + toast.info(pwaSettingsCopy.toasts.update) } const handleClearCache = () => { clearCache() - toast.success('Cache cleared! Reloading...') + toast.success(pwaSettingsCopy.toasts.cacheCleared) } const handleNotificationToggle = async (enabled: boolean) => { if (enabled) { const permission = await requestNotificationPermission() setNotificationPermission(permission as NotificationPermission) - - if (permission === 'granted') { - toast.success('Notifications enabled') - } else { - toast.error('Notification permission denied') - } - } - } - const getPermissionIcon = () => { - switch (notificationPermission) { - case 'granted': - return - case 'denied': - return - default: - return + if (permission === 'granted') { + toast.success(pwaSettingsCopy.toasts.notificationsEnabled) + } else { + toast.error(pwaSettingsCopy.toasts.notificationsDenied) + } } } return (
-

PWA Settings

-

- Configure Progressive Web App features and behavior -

+

{pwaSettingsCopy.header.title}

+

{pwaSettingsCopy.header.description}

- -
-
-

Installation Status

-

- Install the app for offline access and better performance -

-
- -
-
- -
- -

- {isInstalled ? 'Installed' : isInstallable ? 'Available' : 'Not available'} -

-
-
-
- {isInstalled && ( - Installed - )} - {isInstallable && !isInstalled && ( - - )} - {!isInstallable && !isInstalled && ( - Not Available - )} -
-
-
-
+
-

Connection Status

-

- Current network connectivity status -

+

{pwaSettingsCopy.connection.title}

+

{pwaSettingsCopy.connection.description}

@@ -154,142 +102,52 @@ export function PWASettings() { )}
- +

- {isOnline ? 'Connected to internet' : 'Working offline'} + {isOnline ? pwaSettingsCopy.connection.status.online : pwaSettingsCopy.connection.status.offline}

- {isOnline ? 'Online' : 'Offline'} + {isOnline ? pwaSettingsCopy.connection.badge.online : pwaSettingsCopy.connection.badge.offline}
- {isUpdateAvailable && ( - -
-
-

Update Available

-

- A new version of the app is ready to install -

-
+ -
-
- -
- -

- Update now for latest features -

-
-
- -
-
-
- )} + + +
-

Notifications

-

- Receive updates about your projects and builds -

-
- -
-
- -
- -
-

- Permission: {notificationPermission} -

- {getPermissionIcon()} -
-
-
- -
- - {notificationPermission === 'denied' && ( -
- Notifications are blocked. Please enable them in your browser settings. -
- )} -
-
- - -
-
-

Cache Management

-

- Manage offline storage and cached resources -

-
- - - -
-
- - {cacheSize} -
- -
- - - {registration ? 'Active' : 'Inactive'} - -
-
- - - - - -

- This will remove all cached files and reload the app -

-
-
- - -
-
-

PWA Features

-

- Progressive Web App capabilities -

+

{pwaSettingsCopy.features.title}

+

{pwaSettingsCopy.features.description}

- Offline Support + {pwaSettingsCopy.features.items.offline}
- Installable + {pwaSettingsCopy.features.items.installable} {isInstallable || isInstalled ? ( ) : ( @@ -297,11 +155,11 @@ export function PWASettings() { )}
- Background Sync + {pwaSettingsCopy.features.items.backgroundSync}
- Push Notifications + {pwaSettingsCopy.features.items.pushNotifications} {'Notification' in window ? ( ) : ( @@ -309,7 +167,7 @@ export function PWASettings() { )}
- App Shortcuts + {pwaSettingsCopy.features.items.shortcuts}
diff --git a/src/components/pwa-settings/CacheSection.tsx b/src/components/pwa-settings/CacheSection.tsx new file mode 100644 index 0000000..b918021 --- /dev/null +++ b/src/components/pwa-settings/CacheSection.tsx @@ -0,0 +1,66 @@ +import { Badge } from '@/components/ui/badge' +import { Button } from '@/components/ui/button' +import { Card } from '@/components/ui/card' +import { Label } from '@/components/ui/label' +import { Separator } from '@/components/ui/separator' +import { Trash } from '@phosphor-icons/react' + +interface CacheSectionProps { + cacheSize: string + hasRegistration: boolean + onClearCache: () => void + copy: { + title: string + description: string + labels: { + size: string + serviceWorker: string + } + status: { + active: string + inactive: string + } + action: { + clear: string + } + helper: string + } +} + +export function CacheSection({ cacheSize, hasRegistration, onClearCache, copy }: CacheSectionProps) { + return ( + +
+
+

{copy.title}

+

{copy.description}

+
+ + + +
+
+ + {cacheSize} +
+ +
+ + + {hasRegistration ? copy.status.active : copy.status.inactive} + +
+
+ + + + + +

{copy.helper}

+
+
+ ) +} diff --git a/src/components/pwa-settings/InstallSection.tsx b/src/components/pwa-settings/InstallSection.tsx new file mode 100644 index 0000000..502c7e0 --- /dev/null +++ b/src/components/pwa-settings/InstallSection.tsx @@ -0,0 +1,68 @@ +import { Badge } from '@/components/ui/badge' +import { Button } from '@/components/ui/button' +import { Card } from '@/components/ui/card' +import { Label } from '@/components/ui/label' +import { Download } from '@phosphor-icons/react' + +interface InstallSectionProps { + isInstalled: boolean + isInstallable: boolean + onInstall: () => void + copy: { + title: string + description: string + label: string + status: { + installed: string + available: string + notAvailable: string + } + badge: { + installed: string + notAvailable: string + } + action: { + install: string + } + } +} + +export function InstallSection({ isInstalled, isInstallable, onInstall, copy }: InstallSectionProps) { + const statusText = isInstalled + ? copy.status.installed + : isInstallable + ? copy.status.available + : copy.status.notAvailable + + return ( + +
+
+

{copy.title}

+

{copy.description}

+
+ +
+
+ +
+ +

{statusText}

+
+
+
+ {isInstalled && {copy.badge.installed}} + {isInstallable && !isInstalled && ( + + )} + {!isInstallable && !isInstalled && ( + {copy.badge.notAvailable} + )} +
+
+
+
+ ) +} diff --git a/src/components/pwa-settings/NotificationsSection.tsx b/src/components/pwa-settings/NotificationsSection.tsx new file mode 100644 index 0000000..cf8c54b --- /dev/null +++ b/src/components/pwa-settings/NotificationsSection.tsx @@ -0,0 +1,66 @@ +import { Card } from '@/components/ui/card' +import { Label } from '@/components/ui/label' +import { Switch } from '@/components/ui/switch' +import { Bell, CheckCircle, Question, XCircle } from '@phosphor-icons/react' + +interface NotificationsSectionProps { + permission: NotificationPermission + onToggle: (enabled: boolean) => void + copy: { + title: string + description: string + label: string + permissionLabel: string + blocked: string + } +} + +export function NotificationsSection({ permission, onToggle, copy }: NotificationsSectionProps) { + const getPermissionIcon = () => { + switch (permission) { + case 'granted': + return + case 'denied': + return + default: + return + } + } + + return ( + +
+
+

{copy.title}

+

{copy.description}

+
+ +
+
+ +
+ +
+

+ {copy.permissionLabel} {permission} +

+ {getPermissionIcon()} +
+
+
+ +
+ + {permission === 'denied' && ( +
+ {copy.blocked} +
+ )} +
+
+ ) +} diff --git a/src/components/pwa-settings/UpdateSection.tsx b/src/components/pwa-settings/UpdateSection.tsx new file mode 100644 index 0000000..cb57a50 --- /dev/null +++ b/src/components/pwa-settings/UpdateSection.tsx @@ -0,0 +1,44 @@ +import { Button } from '@/components/ui/button' +import { Card } from '@/components/ui/card' +import { Label } from '@/components/ui/label' +import { CloudArrowDown } from '@phosphor-icons/react' + +interface UpdateSectionProps { + isUpdateAvailable: boolean + onUpdate: () => void + copy: { + title: string + description: string + label: string + status: string + action: string + } +} + +export function UpdateSection({ isUpdateAvailable, onUpdate, copy }: UpdateSectionProps) { + if (!isUpdateAvailable) { + return null + } + + return ( + +
+
+

{copy.title}

+

{copy.description}

+
+ +
+
+ +
+ +

{copy.status}

+
+
+ +
+
+
+ ) +} diff --git a/src/data/pwa-settings.json b/src/data/pwa-settings.json new file mode 100644 index 0000000..680d2fa --- /dev/null +++ b/src/data/pwa-settings.json @@ -0,0 +1,89 @@ +{ + "header": { + "title": "PWA Settings", + "description": "Configure Progressive Web App features and behavior" + }, + "install": { + "title": "Installation Status", + "description": "Install the app for offline access and better performance", + "label": "App Installation", + "status": { + "installed": "Installed", + "available": "Available", + "notAvailable": "Not available" + }, + "badge": { + "installed": "Installed", + "notAvailable": "Not Available" + }, + "action": { + "install": "Install Now" + } + }, + "connection": { + "title": "Connection Status", + "description": "Current network connectivity status", + "label": "Network Status", + "status": { + "online": "Connected to internet", + "offline": "Working offline" + }, + "badge": { + "online": "Online", + "offline": "Offline" + } + }, + "update": { + "title": "Update Available", + "description": "A new version of the app is ready to install", + "label": "App Update", + "status": "Update now for latest features", + "action": "Update Now" + }, + "notifications": { + "title": "Notifications", + "description": "Receive updates about your projects and builds", + "label": "Push Notifications", + "permissionLabel": "Permission:", + "blocked": "Notifications are blocked. Please enable them in your browser settings." + }, + "cache": { + "title": "Cache Management", + "description": "Manage offline storage and cached resources", + "labels": { + "size": "Cache Size", + "serviceWorker": "Service Worker" + }, + "status": { + "active": "Active", + "inactive": "Inactive" + }, + "action": { + "clear": "Clear Cache & Reload" + }, + "helper": "This will remove all cached files and reload the app", + "storageUnit": "MB" + }, + "features": { + "title": "PWA Features", + "description": "Progressive Web App capabilities", + "items": { + "offline": "Offline Support", + "installable": "Installable", + "backgroundSync": "Background Sync", + "pushNotifications": "Push Notifications", + "shortcuts": "App Shortcuts" + } + }, + "toasts": { + "installSuccess": "App installed successfully!", + "installCancelled": "Installation cancelled", + "update": "Updating app...", + "cacheCleared": "Cache cleared! Reloading...", + "notificationsEnabled": "Notifications enabled", + "notificationsDenied": "Notification permission denied" + }, + "defaults": { + "cacheCalculating": "Calculating..." + } +}