feat(RECIPE-0009): complete iteration 0 — deduplication, notifications, UI improvements
This commit is contained in:
131
src/routes/test/+page.svelte
Normal file
131
src/routes/test/+page.svelte
Normal file
@@ -0,0 +1,131 @@
|
||||
<script lang="ts">
|
||||
import { pushNotificationManager, type NotificationState } from '$lib/client/PushNotificationManager';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let viewModel = $state<NotificationState>({
|
||||
supported: false,
|
||||
permission: 'default',
|
||||
subscribed: false,
|
||||
loading: false,
|
||||
error: null
|
||||
});
|
||||
|
||||
let testLoading = $state<boolean>(false);
|
||||
let testMessage = $state<string | null>(null);
|
||||
let unsubscribe: (() => void) | null = null;
|
||||
|
||||
onMount(() => {
|
||||
unsubscribe = pushNotificationManager.onStateChange((newState) => {
|
||||
viewModel = newState;
|
||||
});
|
||||
|
||||
return () => {
|
||||
unsubscribe?.();
|
||||
};
|
||||
});
|
||||
|
||||
async function sendTestNotification(type: 'success' | 'error' | 'progress') {
|
||||
testLoading = true;
|
||||
testMessage = null;
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/notifications/test', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ type })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to send test notification');
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
testMessage = `✓ Test ${type} notification sent to ${result.subscriberCount} subscriber(s)`;
|
||||
} catch (error) {
|
||||
testMessage = `✗ Error: ${error instanceof Error ? error.message : 'Unknown error'}`;
|
||||
} finally {
|
||||
testLoading = false;
|
||||
|
||||
setTimeout(() => {
|
||||
testMessage = null;
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>InstaRecipe - Notification Tests</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="mx-auto p-6 max-w-4xl">
|
||||
<div class="mb-8">
|
||||
<h1 class="text-3xl font-bold mb-2">Notification Testing</h1>
|
||||
<p class="text-gray-600">Debug endpoint for testing push notifications</p>
|
||||
</div>
|
||||
|
||||
{#if !viewModel.subscribed}
|
||||
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-4 mb-6">
|
||||
<div class="flex items-start space-x-2">
|
||||
<svg class="w-5 h-5 text-yellow-400 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 15.5c-.77.833.192 2.5 1.732 2.5z"></path>
|
||||
</svg>
|
||||
<div>
|
||||
<div class="text-sm font-medium text-yellow-800">Not Subscribed</div>
|
||||
<div class="text-sm text-yellow-700">
|
||||
You must enable push notifications on the <a href="/" class="underline">homepage</a> before testing.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="bg-white border rounded-lg shadow-sm p-6">
|
||||
<h2 class="text-lg font-medium text-gray-900 mb-4">Test Notifications</h2>
|
||||
<p class="text-sm text-gray-600 mb-6">
|
||||
Send test notifications to verify your subscription is working correctly.
|
||||
</p>
|
||||
|
||||
<div class="flex flex-wrap gap-3 mb-6">
|
||||
<button
|
||||
onclick={() => sendTestNotification('success')}
|
||||
disabled={testLoading || !viewModel.subscribed}
|
||||
class="px-4 py-2 bg-green-600 text-white text-sm font-medium rounded-lg hover:bg-green-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
{testLoading ? 'Sending...' : 'Test Success'}
|
||||
</button>
|
||||
|
||||
<button
|
||||
onclick={() => sendTestNotification('error')}
|
||||
disabled={testLoading || !viewModel.subscribed}
|
||||
class="px-4 py-2 bg-red-600 text-white text-sm font-medium rounded-lg hover:bg-red-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
{testLoading ? 'Sending...' : 'Test Error'}
|
||||
</button>
|
||||
|
||||
<button
|
||||
onclick={() => sendTestNotification('progress')}
|
||||
disabled={testLoading || !viewModel.subscribed}
|
||||
class="px-4 py-2 bg-blue-600 text-white text-sm font-medium rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
>
|
||||
{testLoading ? 'Sending...' : 'Test Progress'}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if testMessage}
|
||||
<div class="p-3 rounded-lg {testMessage.startsWith('✓') ? 'bg-green-50 border border-green-200' : 'bg-red-50 border border-red-200'}">
|
||||
<div class="flex items-start space-x-2">
|
||||
<svg class="w-4 h-4 flex-shrink-0 mt-0.5 {testMessage.startsWith('✓') ? 'text-green-400' : 'text-red-400'}" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d={testMessage.startsWith('✓') ? "M5 13l4 4L19 7" : "M6 18L18 6M6 6l12 12"}></path>
|
||||
</svg>
|
||||
<div class="text-sm {testMessage.startsWith('✓') ? 'text-green-800' : 'text-red-800'}">
|
||||
{testMessage}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<a href="/" class="text-sm text-blue-600 hover:text-blue-700">← Back to Dashboard</a>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user