Pedro Gomes b7e3208eb2 MAI CALL - step 12
Passo 12 completo. Build limpo, AC server-side totalmente verificado.

O que foi implementado:

lib/queue/ — camada de persistência offline:

db.ts — Dexie 4 com tabelas pending e deadLetters
broadcast.ts — BroadcastChannel helper (mai-call-sync) para comunicar entre tabs
sync.ts — loop de sync com retry/backoff: signPhotoUpload → PUT MinIO → create; 409 = sucesso; 4xx = dead-letter; erros de rede = paragem + retry na próxima volta
SyncProvider — React Context que:

Arranca sync ao reconectar (online event + visibilitychange)
Polling de 10s como fallback
Regista Background Sync API quando disponível
Expõe pendingCount / deadLetterCount via useSyncState()
Formulário (/maintenance/new) — refatorado: ao submeter, escreve em IndexedDB e navega imediatamente para /sent sem esperar pelo servidor. O SyncProvider processa a fila em background.

Feedback visual:

SyncChip na home: "Tudo sincronizado" / "N pedidos por enviar" / erro dead-letter
/maintenance/sent: mostra "Em fila" (Clock) ou "Enviado" (CheckCircle2) reactivamente via BroadcastChannel
Workbox (@ducanh2912/next-pwa) — app shell precaching ativo, para que o app carregue mesmo sem rede depois da primeira visita.
2026-05-16 16:55:59 +01:00

2 lines
7.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

if(!self.define){let e,s={};const n=(n,t)=>(n=new URL(n+".js",t).href,s[n]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=s,document.head.appendChild(e)}else e=n,importScripts(n),s()}).then(()=>{let e=s[n];if(!e)throw new Error(`Module ${n} didnt register its module`);return e}));self.define=(t,a)=>{const c=e||("document"in self?document.currentScript.src:"")||location.href;if(s[c])return;let i={};const r=e=>n(e,c),o={module:{uri:c},exports:i,require:r};s[c]=Promise.all(t.map(e=>o[e]||r(e))).then(e=>(a(...e),i))}}define(["./workbox-5194662c"],function(e){"use strict";importScripts(),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/dynamic-css-manifest.json",revision:"d751713988987e9331980363e24189ce"},{url:"/_next/static/E24ILEIxTT35zMD-Lqk4Z/_buildManifest.js",revision:"57b739a594f4a81ede20407d3eb2f67f"},{url:"/_next/static/E24ILEIxTT35zMD-Lqk4Z/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/_next/static/chunks/2-1fec31df5cccd978.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/207-5830eb1c236921c4.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/366-9f25a484ec1a0ad1.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/453-4f1bf64721542ff1.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/5e89d14c-29448a56658b5c05.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/69.85d4fd0d1cced6f3.js",revision:"85d4fd0d1cced6f3"},{url:"/_next/static/chunks/699-e0dfe35c99f38031.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/718-c610b317eb50f713.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/864.76d176e27ab6eb2e.js",revision:"76d176e27ab6eb2e"},{url:"/_next/static/chunks/app/_not-found/page-27b9c7c9c84d3c3e.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/app/api/auth/%5B...nextauth%5D/route-eb91e6bcaad07c95.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/app/api/trpc/%5Btrpc%5D/route-ac9de9091f551860.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/app/error-b113a02aedbc7163.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/app/layout-4f117dbcc88e9f9d.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/app/maintenance/new/page-5955e116c9dd3501.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/app/maintenance/sent/page-45ea63d2cf48c8ea.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/app/not-found-62acb79750232d66.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/app/page-81637445222f88bf.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/app/select-operator/page-dab79b3f8b754bfc.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/framework-e9d381d8cb9498da.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/main-app-06906c35d26f4210.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/main-ec3a7b1cd2097aab.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/pages/_app-f69aca65b88454b7.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/pages/_error-df94080b8a9a72e7.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/chunks/polyfills-42372ed130431b0a.js",revision:"846118c33b2c0e922d7b3a7676f81f6f"},{url:"/_next/static/chunks/webpack-51c1b9324c7c4d52.js",revision:"E24ILEIxTT35zMD-Lqk4Z"},{url:"/_next/static/css/3295c4d4c839af1a.css",revision:"3295c4d4c839af1a"},{url:"/icon-192.svg",revision:"4b4dfb506ed7eebc6e763bf8f09d75e6"},{url:"/icon-512.svg",revision:"d247a6555ec14dd052372bb297c43ae4"},{url:"/icon-maskable.svg",revision:"2fd823b9a4b1bec7aab84a22921c75c6"},{url:"/manifest.webmanifest",revision:"135f7a5aaec94ede8eb024ac054e5763"},{url:"/swe-worker-5c72df51bb1f6ee0.js",revision:"76fdd3369f623a3edcf74ce2200bfdd0"}],{ignoreURLParametersMatching:[/^utm_/,/^fbclid$/]}),e.cleanupOutdatedCaches(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[{cacheWillUpdate:function(e){return _ref.apply(this,arguments)}}]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:gstatic)\.com\/.*/i,new e.CacheFirst({cacheName:"google-fonts-webfonts",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3})]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:googleapis)\.com\/.*/i,new e.StaleWhileRevalidate({cacheName:"google-fonts-stylesheets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,new e.StaleWhileRevalidate({cacheName:"static-font-assets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800})]}),"GET"),e.registerRoute(/\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,new e.StaleWhileRevalidate({cacheName:"static-image-assets",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:2592e3})]}),"GET"),e.registerRoute(/\/_next\/static.+\.js$/i,new e.CacheFirst({cacheName:"next-static-js-assets",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/image\?url=.+$/i,new e.StaleWhileRevalidate({cacheName:"next-image",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp3|wav|ogg)$/i,new e.CacheFirst({cacheName:"static-audio-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:mp4|webm)$/i,new e.CacheFirst({cacheName:"static-video-assets",plugins:[new e.RangeRequestsPlugin,new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:js)$/i,new e.StaleWhileRevalidate({cacheName:"static-js-assets",plugins:[new e.ExpirationPlugin({maxEntries:48,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:css|less)$/i,new e.StaleWhileRevalidate({cacheName:"static-style-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\/_next\/data\/.+\/.+\.json$/i,new e.StaleWhileRevalidate({cacheName:"next-data",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(/\.(?:json|xml|csv)$/i,new e.NetworkFirst({cacheName:"static-data-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(function(e){var s=e.sameOrigin,n=e.url.pathname;return!(!s||n.startsWith("/api/auth/callback")||!n.startsWith("/api/"))},new e.NetworkFirst({cacheName:"apis",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:16,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(function(e){var s=e.request,n=e.url.pathname,t=e.sameOrigin;return"1"===s.headers.get("RSC")&&"1"===s.headers.get("Next-Router-Prefetch")&&t&&!n.startsWith("/api/")},new e.NetworkFirst({cacheName:"pages-rsc-prefetch",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(function(e){var s=e.request,n=e.url.pathname,t=e.sameOrigin;return"1"===s.headers.get("RSC")&&t&&!n.startsWith("/api/")},new e.NetworkFirst({cacheName:"pages-rsc",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(function(e){var s=e.url.pathname;return e.sameOrigin&&!s.startsWith("/api/")},new e.NetworkFirst({cacheName:"pages",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(function(e){return!e.sameOrigin},new e.NetworkFirst({cacheName:"cross-origin",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:3600})]}),"GET")});