feat(pwa): hors-ligne (app shell + lecture API) et suppression depuis la page d'édition
- sw.ts : API GET, navigation et payloads RSC en network-first (cache en secours hors-ligne) ; écritures non interceptées ; fallback ~offline - edit page : bouton Supprimer avec confirmation (CardDeleteButton)
This commit is contained in:
1 parent
ba5bd8288d
commit
31283ada26
2 files changed
+37
-4
No files matched your search
@@ -1,6 +1,7 @@
|
||||
import type { Metadata } from 'next'
|
||||
import Link from 'next/link'
|
||||
import { notFound } from 'next/navigation'
|
||||
import { CardDeleteButton } from '@/components/card-delete'
|
||||
import { CardForm } from '@/components/card-form'
|
||||
import type { Card, CardInput } from '@/domain/card'
|
||||
import { ApiClientError, cardsApi } from '@/lib/api-client'
|
||||
@@ -33,7 +34,10 @@ export default async function EditCardPage({ params }: { params: Promise<{ id: s
|
||||
>
|
||||
← Retour au détail
|
||||
</Link>
|
||||
<h1 className="mt-2 text-2xl font-bold text-slate-900">{card.question}</h1>
|
||||
<div className="mt-2 flex items-center justify-between gap-4">
|
||||
<h1 className="text-2xl font-bold text-slate-900">{card.question}</h1>
|
||||
<CardDeleteButton cardId={card.id} question={card.question} />
|
||||
</div>
|
||||
</div>
|
||||
<CardForm mode="edit" cardId={card.id} initial={initial} />
|
||||
</main>
|
||||
|
||||
+32
-3
@@ -1,7 +1,7 @@
|
||||
/// <reference lib="webworker" />
|
||||
import { defaultCache } from '@serwist/turbopack/worker'
|
||||
import type { PrecacheEntry, RuntimeCaching, SerwistGlobalConfig } from 'serwist'
|
||||
import { NetworkOnly, Serwist } from 'serwist'
|
||||
import { ExpirationPlugin, NetworkFirst, Serwist } from 'serwist'
|
||||
|
||||
declare global {
|
||||
interface WorkerGlobalScope extends SerwistGlobalConfig {
|
||||
@@ -11,11 +11,40 @@ declare global {
|
||||
|
||||
declare const self: ServiceWorkerGlobalScope
|
||||
|
||||
// Ne jamais mettre en cache les appels API
|
||||
// API : lectures (GET) en réseau d'abord, servies depuis le cache en secours
|
||||
// hors-ligne. Les écritures (POST/PUT/DELETE) ne sont pas interceptées par le
|
||||
// service worker et passent toujours par le réseau.
|
||||
const runtimeCaching: RuntimeCaching[] = [
|
||||
{
|
||||
matcher: ({ sameOrigin, url }) => sameOrigin && url.pathname.startsWith('/api/'),
|
||||
handler: new NetworkOnly(),
|
||||
handler: new NetworkFirst({
|
||||
networkTimeoutSeconds: 3,
|
||||
cacheName: 'api-network-first',
|
||||
plugins: [
|
||||
new ExpirationPlugin({
|
||||
maxEntries: 200,
|
||||
maxAgeSeconds: 7 * 24 * 60 * 60,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
},
|
||||
// Navigation : réseau d'abord (pages toujours fraîches après déploiement),
|
||||
// cache en secours uniquement hors-ligne
|
||||
{
|
||||
matcher: ({ request }) => request.mode === 'navigate',
|
||||
handler: new NetworkFirst({
|
||||
networkTimeoutSeconds: 3,
|
||||
cacheName: 'pages-network-first',
|
||||
}),
|
||||
},
|
||||
// Payloads RSC des navigations côté client : réseau d'abord
|
||||
{
|
||||
matcher: ({ request, sameOrigin }) =>
|
||||
sameOrigin && request.headers.get('rsc') === '1',
|
||||
handler: new NetworkFirst({
|
||||
networkTimeoutSeconds: 3,
|
||||
cacheName: 'rsc-network-first',
|
||||
}),
|
||||
},
|
||||
...defaultCache,
|
||||
]
|
||||
|
||||
Reference in new issue
Block a user