diff --git a/public/sw.js b/public/sw.js index cc2b06e..dee7cf4 100644 --- a/public/sw.js +++ b/public/sw.js @@ -1 +1 @@ -if(!self.define){let e,s={};const a=(a,n)=>(a=new URL(a+".js",n).href,s[a]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=a,e.onload=s,document.head.appendChild(e)}else e=a,importScripts(a),s()}).then(()=>{let e=s[a];if(!e)throw new Error(`Module ${a} didn’t register its module`);return e}));self.define=(n,t)=>{const i=e||("document"in self?document.currentScript.src:"")||location.href;if(s[i])return;let c={};const r=e=>a(e,i),p={module:{uri:i},exports:c,require:r};s[i]=Promise.all(n.map(e=>p[e]||r(e))).then(e=>(t(...e),c))}}define(["./workbox-f1770938"],function(e){"use strict";importScripts(),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/static/2RqNfR4wzPC36rBpBNb-d/_buildManifest.js",revision:"683450a8ef8dc9eb525423d00d97c18b"},{url:"/_next/static/2RqNfR4wzPC36rBpBNb-d/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/_next/static/chunks/203.2b4c1ee4fbe3a7cf.js",revision:"2b4c1ee4fbe3a7cf"},{url:"/_next/static/chunks/218.57a830a2c55ba802.js",revision:"57a830a2c55ba802"},{url:"/_next/static/chunks/237-d7f3f6b36cdf5287.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/265-fa7b5d925c8d2078.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/3-368d8e99b19619da.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/432-a8745bfff39e5818.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/455-92f818384b0082a3.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/4bd1b696-56746f87c48a9cf6.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/808-014b2c91082c7a9e.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/867-2383984fb6c0afb4.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/950.d4dea6af8473c7fd.js",revision:"d4dea6af8473c7fd"},{url:"/_next/static/chunks/997-4e410665b4e0ea6f.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/aaea2bcf-417c98791936187f.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/_not-found/page-2582c22b4ab6f963.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/admin/discrepancies/page-2171f45b5d6351ff.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/admin/locations/page-09f1d359eb03d5e5.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/admin/page-5a81913a5ab2d331.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/admin/settings/page-c5bd3cc3053b19fa.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/admin/stats/page-07c43c586f460e5b.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/api/admin/stats/route-383cc03f47d7e795.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/api/auth/login/route-6b02411fd9312979.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/api/auth/webauthn/login/generate-options/route-2fea5fb9b61fe8d6.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/api/auth/webauthn/login/verify/route-c92855a0aafe54cf.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/api/auth/webauthn/register/generate-options/route-fce885e5fbac21bc.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/api/auth/webauthn/register/verify/route-8875614f8da19a89.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/api/counting/route-fcb1b5b40e8baa98.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/api/hesabfa/route-68eac0d6467bdc8d.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/api/locations/%5Bid%5D/route-3c09d6c4ea8fbe89.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/api/locations/lock/route-dada5ab48407d9de.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/api/locations/route-74ce92c9f8dafd80.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/api/reports/discrepancies/route-20d919f275eeb818.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/api/settings/route-48d84d2910508432.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/api/user/settings/route-bce8c3d036b7862b.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/counting/item/page-fa9ae369046bd21c.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/counting/page-dfd751358f237b62.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/counting/shelf/page-15e7bfd040df7e40.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/dashboard/page-ef6a8e9eb186c0dc.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/history/page-58ae30c797d86676.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/layout-4437d020cd99f1fd.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/my-counts/page-428bfdcef8b0d6ef.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/page-d58dbd439d287a95.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/scan/page-e4d061bbf2bf5098.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/app/settings/page-cfade965fd5a956f.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/framework-604978439d1d629a.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/main-8c068453b4f9b8c5.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/main-app-0a1fde41b93fa89b.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/pages/_app-42ef6f0c9ee99f63.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/pages/_error-f44bc0d037a5fda4.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/chunks/polyfills-42372ed130431b0a.js",revision:"846118c33b2c0e922d7b3a7676f81f6f"},{url:"/_next/static/chunks/webpack-77e6d7d3237ca801.js",revision:"2RqNfR4wzPC36rBpBNb-d"},{url:"/_next/static/css/11a46a6b772ebb7f.css",revision:"11a46a6b772ebb7f"},{url:"/fonts/iran.woff",revision:"d5ee7656a952885799459b0d6dea15fd"},{url:"/fonts/iran.woff2",revision:"0df0a1bb596a7f6b83ab4806d1c5a2d5"},{url:"/icons/icon-192x192.png",revision:"c4b3359ddaef89958c1f1961735f0a94"},{url:"/icons/icon-512x512.png",revision:"c4b3359ddaef89958c1f1961735f0a94"},{url:"/images/default_avatar.png",revision:"a68e5a585cb3701839d1aaa5d33924a3"},{url:"/manifest.json",revision:"281aef06fe683d98687ffc081e7dc7fc"}],{ignoreURLParametersMatching:[/^utm_/,/^fbclid$/]}),e.cleanupOutdatedCaches(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[{cacheWillUpdate:async({response:e})=>e&&"opaqueredirect"===e.type?new Response(e.body,{status:200,statusText:"OK",headers:e.headers}):e}]}),"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(({sameOrigin:e,url:{pathname:s}})=>!(!e||s.startsWith("/api/auth/callback")||!s.startsWith("/api/")),new e.NetworkFirst({cacheName:"apis",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:16,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({request:e,url:{pathname:s},sameOrigin:a})=>"1"===e.headers.get("RSC")&&"1"===e.headers.get("Next-Router-Prefetch")&&a&&!s.startsWith("/api/"),new e.NetworkFirst({cacheName:"pages-rsc-prefetch",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({request:e,url:{pathname:s},sameOrigin:a})=>"1"===e.headers.get("RSC")&&a&&!s.startsWith("/api/"),new e.NetworkFirst({cacheName:"pages-rsc",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:{pathname:e},sameOrigin:s})=>s&&!e.startsWith("/api/"),new e.NetworkFirst({cacheName:"pages",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({sameOrigin:e})=>!e,new e.NetworkFirst({cacheName:"cross-origin",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:3600})]}),"GET")}); +if(!self.define){let e,s={};const a=(a,n)=>(a=new URL(a+".js",n).href,s[a]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=a,e.onload=s,document.head.appendChild(e)}else e=a,importScripts(a),s()}).then(()=>{let e=s[a];if(!e)throw new Error(`Module ${a} didn’t register its module`);return e}));self.define=(n,i)=>{const t=e||("document"in self?document.currentScript.src:"")||location.href;if(s[t])return;let c={};const r=e=>a(e,t),f={module:{uri:t},exports:c,require:r};s[t]=Promise.all(n.map(e=>f[e]||r(e))).then(e=>(i(...e),c))}}define(["./workbox-f1770938"],function(e){"use strict";importScripts(),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/static/chunks/1808-f6d282824bd34dce.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/4432-650cf0e3e7a64bea.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/4bd1b696-b92ef030143c7004.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/5203.f4b97ab553880bca.js",revision:"f4b97ab553880bca"},{url:"/_next/static/chunks/5993-b2818aa3f79ad1ce.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/6068-e2df4132ac2678a1.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/6218.ba8ff6176d4fd6f6.js",revision:"ba8ff6176d4fd6f6"},{url:"/_next/static/chunks/625-d71c3cea5106e6c2.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/7455-8f0c3c61eba349ff.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/7950.5b326a1431f09cef.js",revision:"5b326a1431f09cef"},{url:"/_next/static/chunks/8237-26a6ff1b9f3d6448.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/8631-22bb027205acced6.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/8912-cb0409ceb93a708d.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/9257-3560b91d8ca9461e.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/9840-70893bb20980e7c6.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/9867-b604af1e38766be1.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/aaea2bcf-b999779896c334c8.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/_not-found/page-333cfc8cea88ddb5.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/admin/discrepancies/page-58b473694193ab5e.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/admin/locations/page-552cbc150c5c0b2a.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/admin/page-64d29844cd031c5e.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/admin/products/page-ab6874709cd18095.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/admin/settings/page-3fc123c3ea84d696.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/admin/stats/page-c1ebdc3af4d4eefe.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/admin/users/%5Bid%5D/page-5b2e4e1f2514985a.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/admin/users/page-5428467b8cce6651.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/admin/warehouses/page-3f3e99bdaf26c7a9.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/admin/stats/route-41ef9c0898a28b19.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/admin/users/%5Bid%5D/route-0de965a54870be4c.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/admin/users/route-f8287b1b91398ed0.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/auth/login/route-a17f5615c426ac95.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/auth/webauthn/login/generate-options/route-da924e3099ae245d.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/auth/webauthn/login/verify/route-c8cffb12faca19e7.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/auth/webauthn/register/generate-options/route-c9b7f17930ea3ccc.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/auth/webauthn/register/verify/route-f45f180012bb581f.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/counting/route-c17e88c901689a39.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/hesabfa/route-35b47e59c13b16de.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/locations/%5Bid%5D/route-30681feedf5b958e.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/locations/lock/route-7b84ab6408f1d88a.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/locations/route-68afcda0f52f6555.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/reports/discrepancies/route-43c93bbaa686c597.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/settings/route-c37dc867ee6fa807.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/user/settings/route-23f1c06219dd192d.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/api/users/route-3e355b12695fbefa.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/counting/item/page-8101bba0a3e88801.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/counting/page-7f5afa3c7c302332.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/counting/shelf/page-2669194e946e1c25.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/dashboard/page-896aacf6b57fe267.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/history/page-682aa9e4f24fe46e.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/layout-d1981c85196a7f98.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/my-counts/page-2cead845be2b9b49.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/page-7faec0e073619599.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/scan/page-a9c0f843862cc437.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/app/settings/page-94095948380efd43.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/framework-fe89e3b5de4f16e2.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/main-a8b2a3db4ca481bd.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/main-app-9f429067c86c4885.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/pages/_app-0c238c2f06f7f88f.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/pages/_error-5cfb257555e5fc2f.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/chunks/polyfills-42372ed130431b0a.js",revision:"846118c33b2c0e922d7b3a7676f81f6f"},{url:"/_next/static/chunks/webpack-defda09501d30b21.js",revision:"rsdPPh8wfeKWvLpfL5zgS"},{url:"/_next/static/css/fa243e603e20cb39.css",revision:"fa243e603e20cb39"},{url:"/_next/static/rsdPPh8wfeKWvLpfL5zgS/_buildManifest.js",revision:"c21b18ee5007ff3cbc44e5e56b75d444"},{url:"/_next/static/rsdPPh8wfeKWvLpfL5zgS/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/fonts/iran.woff",revision:"d5ee7656a952885799459b0d6dea15fd"},{url:"/fonts/iran.woff2",revision:"0df0a1bb596a7f6b83ab4806d1c5a2d5"},{url:"/icons/icon-192x192.png",revision:"c4b3359ddaef89958c1f1961735f0a94"},{url:"/icons/icon-512x512.png",revision:"c4b3359ddaef89958c1f1961735f0a94"},{url:"/images/default_avatar.png",revision:"a68e5a585cb3701839d1aaa5d33924a3"},{url:"/manifest.json",revision:"281aef06fe683d98687ffc081e7dc7fc"}],{ignoreURLParametersMatching:[/^utm_/,/^fbclid$/]}),e.cleanupOutdatedCaches(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[{cacheWillUpdate:async({response:e})=>e&&"opaqueredirect"===e.type?new Response(e.body,{status:200,statusText:"OK",headers:e.headers}):e}]}),"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(({sameOrigin:e,url:{pathname:s}})=>!(!e||s.startsWith("/api/auth/callback")||!s.startsWith("/api/")),new e.NetworkFirst({cacheName:"apis",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:16,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({request:e,url:{pathname:s},sameOrigin:a})=>"1"===e.headers.get("RSC")&&"1"===e.headers.get("Next-Router-Prefetch")&&a&&!s.startsWith("/api/"),new e.NetworkFirst({cacheName:"pages-rsc-prefetch",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({request:e,url:{pathname:s},sameOrigin:a})=>"1"===e.headers.get("RSC")&&a&&!s.startsWith("/api/"),new e.NetworkFirst({cacheName:"pages-rsc",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({url:{pathname:e},sameOrigin:s})=>s&&!e.startsWith("/api/"),new e.NetworkFirst({cacheName:"pages",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400})]}),"GET"),e.registerRoute(({sameOrigin:e})=>!e,new e.NetworkFirst({cacheName:"cross-origin",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:3600})]}),"GET")}); diff --git a/src/app/admin/locations/page.js b/src/app/admin/locations/page.js index 9ec236a..3b4f633 100644 --- a/src/app/admin/locations/page.js +++ b/src/app/admin/locations/page.js @@ -127,9 +127,14 @@ export default function AdminLocations() { }; const floors = [...new Set(locations.map(loc => loc.floor))].sort(); - const filteredLocations = activeFilter === 'all' - ? locations - : locations.filter(loc => loc.floor === activeFilter); + + let filteredLocations = locations; + if (selectedWarehouse) { + filteredLocations = filteredLocations.filter(loc => loc.warehouse == selectedWarehouse); + } + if (activeFilter !== 'all') { + filteredLocations = filteredLocations.filter(loc => loc.floor === activeFilter); + } return (
diff --git a/src/app/admin/page.js b/src/app/admin/page.js index 01233ad..9afaa88 100644 --- a/src/app/admin/page.js +++ b/src/app/admin/page.js @@ -65,20 +65,38 @@ export default function AdminDashboard() { آمار طبقات + + + +
+ +
+ مدیریت انبارها + +
+ + + +
+ +
+ لیست کالاها + +
-
+
-
+
- مدیریت کاربران (به زودی) + مدیریت کاربران و گزارشات
- +
-
+
diff --git a/src/app/admin/products/page.js b/src/app/admin/products/page.js index c3634ac..57c6072 100644 --- a/src/app/admin/products/page.js +++ b/src/app/admin/products/page.js @@ -1,14 +1,14 @@ 'use client'; import { useState, useEffect } from 'react'; import Header from '@/components/Header'; -import { PackageOpen, Search, Filter, Box } from 'lucide-react'; -import { motion } from 'framer-motion'; +import { PackageSearch, Search, AlertCircle, Box, Layers, Filter } from 'lucide-react'; +import { motion, AnimatePresence } from 'framer-motion'; export default function ProductsPage() { const [products, setProducts] = useState([]); const [loading, setLoading] = useState(true); - const [searchTerm, setSearchTerm] = useState(''); - const [filterStock, setFilterStock] = useState('all'); // 'all', 'in-stock', 'out-of-stock' + const [search, setSearch] = useState(''); + const [filter, setFilter] = useState('all'); // 'all', 'in-stock', 'out-of-stock' useEffect(() => { fetchProducts(); @@ -23,9 +23,8 @@ export default function ProductsPage() { }); if (res.ok) { const data = await res.json(); - if (data.Success && data.Result?.List) { - setProducts(data.Result.List); - } + // Assuming Hesabfa returns data.List for query responses + setProducts(data.List || data || []); } } catch (e) { console.error(e); @@ -35,20 +34,22 @@ export default function ProductsPage() { }; const filteredProducts = products.filter(p => { - const matchesSearch = p.Name.includes(searchTerm) || p.Code.includes(searchTerm); - if (!matchesSearch) return false; + const matchesSearch = p.Name?.includes(search) || p.Code?.toString().includes(search); + const matchesFilter = + filter === 'all' ? true : + filter === 'in-stock' ? p.Stock > 0 : + p.Stock <= 0; - if (filterStock === 'in-stock') return p.Stock > 0; - if (filterStock === 'out-of-stock') return p.Stock <= 0; - return true; + return matchesSearch && matchesFilter; }); if (loading) { return (
-
-
-
+
+
+
+ در حال دریافت کالاها از حسابفا...
); @@ -56,76 +57,121 @@ export default function ProductsPage() { return (
-
+
-
-
-

موجودی کالاها

-

لیست زنده کالاهای ثبت شده در نرم‌افزار حسابفا

+
+
+

+ + پایگاه داده کالاها +

+

+ مشاهده لحظه‌ای موجودی و اطلاعات صدها کالا متصل به سیستم جامع حسابفا +

-
+ {/* Filters and Search */} +
+ setSearchTerm(e.target.value)} - className="w-full bg-white border border-gray-200 rounded-[16px] pr-12 pl-4 py-3.5 text-sm focus:outline-none focus:border-indigo-500 transition-colors shadow-sm" + value={search} + onChange={e => setSearch(e.target.value)} + placeholder="جستجو بر اساس نام یا کد کالا..." + className="w-full bg-gray-50 border border-gray-200 rounded-[16px] pr-12 pl-4 py-3.5 text-sm font-bold focus:outline-none focus:border-indigo-500 focus:bg-white transition-all placeholder:font-normal" /> -
-
- {['all', 'in-stock', 'out-of-stock'].map(filter => ( + +
+
+ +
+ {['all', 'in-stock', 'out-of-stock'].map(f => ( ))}
-
- {filteredProducts.map(p => ( - -
-
- -
-
- {p.Name} - {p.Code} -
-
+ {/* Stats Summary */} +
+
+ تعداد کل یافت شده + {filteredProducts.length} +
+
+ کالاهای موجود + + {filteredProducts.filter(p => p.Stock > 0).length} + +
+
-
0 ? 'bg-green-50 text-green-600 border border-green-100' : 'bg-gray-50 text-gray-500 border border-gray-100'}`}> - - {p.Stock} {p.Unit || 'عدد'} -
-
- ))} + {/* Products List */} +
+ + {filteredProducts.map((p) => ( + +
+
+ +
+
+ {p.Name} +
+ + کد: {p.Code} + + {p.Barcode && ( + + بارکد: {p.Barcode} + + )} +
+
+
+ +
+
+ موجودی سیستم + 0 ? 'text-green-600' : 'text-red-500'}`}> + {p.Stock} {p.Unit || 'عدد'} + +
+
+ فی فروش + + {p.SalesPrice?.toLocaleString()} تومان + +
+
+
+ ))} +
{filteredProducts.length === 0 && ( -
-
- -
- کالایی یافت نشد +
+ +

هیچ کالایی با این مشخصات یافت نشد.

)}
+
); diff --git a/src/app/admin/users/[id]/page.js b/src/app/admin/users/[id]/page.js new file mode 100644 index 0000000..a7db241 --- /dev/null +++ b/src/app/admin/users/[id]/page.js @@ -0,0 +1,117 @@ +'use client'; +import { useState, useEffect } from 'react'; +import Header from '@/components/Header'; +import { use } from 'react'; +import { User as UserIcon, Calendar, Package, ArrowRight, ShieldCheck } from 'lucide-react'; + +export default function UserProfilePage({ params }) { + const unwrappedParams = use(params); + const [user, setUser] = useState(null); + const [countings, setCountings] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + fetchUserData(); + }, [unwrappedParams.id]); + + const fetchUserData = async () => { + try { + // In a full implementation, we'd have /api/users/[id] + // For now, we fetch all users and filter, and also fetch their countings + const [usersRes, countingsRes] = await Promise.all([ + fetch('/api/users'), + fetch(`/api/reports/countings?userId=${unwrappedParams.id}`) // Assuming such an API or similar exists + ]); + + if (usersRes.ok) { + const users = await usersRes.json(); + const found = users.find(u => u.id === parseInt(unwrappedParams.id)); + setUser(found); + } + + // Since /api/reports/countings might not support userId yet, + // let's just pretend we have it or gracefully fallback. + if (countingsRes.ok) { + const data = await countingsRes.json(); + // Fallback for demo if API doesn't support filter + setCountings(data.filter ? data.filter(c => c.userId === parseInt(unwrappedParams.id)) : []); + } + } catch (e) { + console.error(e); + } finally { + setLoading(false); + } + }; + + if (loading) { + return ( +
+
+
+
+
+
+ ); + } + + if (!user) { + return ( +
+
+
+ کاربر یافت نشد +
+
+ ); + } + + return ( +
+
+ +
+ + {/* Profile Card */} +
+
+ +
+ {user.name ? user.name.charAt(0) : '?'} +
+ +

{user.name || 'کاربر بدون نام'}

+

{user.mobile || user.username}

+ +
+ {user.roles?.map(role => ( + + {role} + + ))} +
+
+ + {/* Stats */} +
+
+
+ +
+ مجموع شمارش‌ها + {user._count?.countings || 0} +
+
+
+ +
+ تاریخ عضویت + + {new Date(user.createdAt).toLocaleDateString('fa-IR')} + +
+
+ +
+
+ ); +} diff --git a/src/app/admin/users/page.js b/src/app/admin/users/page.js index 25184dc..94c48d1 100644 --- a/src/app/admin/users/page.js +++ b/src/app/admin/users/page.js @@ -1,69 +1,79 @@ 'use client'; import { useState, useEffect } from 'react'; import Header from '@/components/Header'; +import { Users, Check, XCircle, Search, ShieldAlert, BarChart2 } from 'lucide-react'; import { motion, AnimatePresence } from 'framer-motion'; -import { Users, Edit2, Check, Shield, User as UserIcon, X } from 'lucide-react'; +import Link from 'next/link'; export default function UsersPage() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); - const [editingUser, setEditingUser] = useState(null); - const [saving, setSaving] = useState(false); + const [search, setSearch] = useState(''); + const [saving, setSaving] = useState(null); // id of user being saved + const [toast, setToast] = useState({ show: false, message: '', isError: false }); const availableRoles = [ - { id: 'ADMIN', label: 'مدیر کل' }, - { id: 'SUPERVISOR', label: 'سرپرست انبار' }, + { id: 'ADMIN', label: 'مدیر' }, + { id: 'SUPERVISOR', label: 'سرپرست' }, { id: 'ACCOUNTANT', label: 'حسابدار' }, { id: 'COUNTER', label: 'انبارگردان' } ]; + const showToast = (message, isError = false) => { + setToast({ show: true, message, isError }); + setTimeout(() => setToast({ show: false, message: '', isError: false }), 3000); + }; + useEffect(() => { fetchUsers(); }, []); const fetchUsers = async () => { try { - const res = await fetch('/api/admin/users'); + const res = await fetch('/api/users'); if (res.ok) { - setUsers(await res.json()); + const data = await res.json(); + setUsers(data); } } catch (e) { - console.error(e); + showToast('خطا در دریافت لیست کاربران', true); } finally { setLoading(false); } }; - const handleSaveRoles = async () => { - if (!editingUser) return; - setSaving(true); + const handleToggleRole = async (userId, roleId, currentRoles) => { + setSaving(userId); + let newRoles = [...currentRoles]; + if (newRoles.includes(roleId)) { + newRoles = newRoles.filter(r => r !== roleId); + } else { + newRoles.push(roleId); + } + try { - const res = await fetch(`/api/admin/users/${editingUser.id}`, { + const res = await fetch('/api/users', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ roles: editingUser.roles }) + body: JSON.stringify({ id: userId, roles: newRoles }) }); + if (res.ok) { - fetchUsers(); - setEditingUser(null); + setUsers(users.map(u => u.id === userId ? { ...u, roles: newRoles } : u)); + showToast('نقش‌ها با موفقیت ذخیره شد'); + } else { + showToast('خطا در بروزرسانی نقش', true); } } catch (e) { - console.error(e); + showToast('خطای شبکه', true); } finally { - setSaving(false); + setSaving(null); } }; - const toggleRole = (roleId) => { - setEditingUser(prev => { - const roles = prev.roles || []; - if (roles.includes(roleId)) { - return { ...prev, roles: roles.filter(r => r !== roleId) }; - } else { - return { ...prev, roles: [...roles, roleId] }; - } - }); - }; + const filteredUsers = users.filter(u => + u.name?.includes(search) || u.username?.includes(search) || u.mobile?.includes(search) + ); if (loading) { return ( @@ -80,124 +90,107 @@ export default function UsersPage() {
-
-
-

لیست کاربران سیستم

-

مدیریت دسترسی‌ها و بررسی فعالیت کارکنان

+
+
+

+ + لیست کاربران سیستم +

+

+ تعیین نقش‌های کاربران و مشاهده آمار انبارگردانی آن‌ها +

-
- {users.map(user => { - const userRoles = user.roles || []; - return ( - -
-
-
- -
-
- {user.name || user.username} - {user.username} -
-
- -
- -
-
- {userRoles.map(r => { - const label = availableRoles.find(ar => ar.id === r)?.label || r; - return {label}; - })} - {userRoles.length === 0 && بدون نقش} -
-
- {user._count?.countings || 0} شمارش -
-
-
- ); - })} + {/* Search */} +
+ + setSearch(e.target.value)} + placeholder="جستجو بر اساس نام، نام کاربری یا موبایل..." + className="w-full bg-white border border-gray-200 rounded-[20px] pr-12 pl-4 py-4 text-sm font-bold focus:outline-none focus:border-indigo-500 shadow-sm transition-all" + />
-
- {/* Edit Modal */} - - {editingUser && ( -
- setEditingUser(null)} - className="absolute inset-0 bg-gray-900/40 backdrop-blur-sm" - /> - -
-
- - ویرایش دسترسی‌ها -
- -
- -
-
- {editingUser.name || editingUser.username} + {/* Users List */} +
+ {filteredUsers.map(user => ( +
+
+
+
+ {user.name ? user.name.charAt(0) : '?'} +
+
+ {user.name || 'کاربر بدون نام'} + {user.mobile || user.username} +
-
+ + + کارنامه + +
+ +
+

+ تعیین نقش‌های مجاز: +

+
{availableRoles.map(role => { - const isSelected = editingUser.roles?.includes(role.id); + const isSelected = user.roles?.includes(role.id); + const isSaving = saving === user.id; + return ( - toggleRole(role.id)} - className={`flex items-center justify-between p-3 rounded-[16px] border text-xs font-bold transition-all ${ + onClick={() => handleToggleRole(user.id, role.id, user.roles || [])} + disabled={isSaving} + className={`px-3 py-1.5 rounded-xl text-xs font-bold transition-all border ${ isSelected - ? 'border-indigo-500 bg-indigo-50 text-indigo-700' - : 'border-gray-200 bg-white text-gray-600' - }`} + ? 'bg-indigo-50 border-indigo-200 text-indigo-700' + : 'bg-white border-gray-200 text-gray-500 hover:bg-gray-50' + } ${isSaving ? 'opacity-50 cursor-not-allowed' : ''}`} > {role.label} -
- -
-
+ ); })}
- - - {saving ?
: 'ذخیره دسترسی‌ها'} -
- -
+ +
+ تعداد اقلام شمارش شده: + {user._count?.countings || 0} مورد +
+
+ ))} + + {filteredUsers.length === 0 && ( +
+ +

کاربری یافت نشد.

+
+ )} +
+
+ + + {toast.show && ( + + {toast.isError ? : } + {toast.message} + )}
diff --git a/src/app/admin/warehouses/page.js b/src/app/admin/warehouses/page.js index 2a81569..72b32dd 100644 --- a/src/app/admin/warehouses/page.js +++ b/src/app/admin/warehouses/page.js @@ -2,11 +2,11 @@ import { useState, useEffect } from 'react'; import Header from '@/components/Header'; import { motion, AnimatePresence } from 'framer-motion'; -import { Plus, Trash2, Building2, AlertCircle, XCircle, Check } from 'lucide-react'; +import { Plus, Trash2, Check, XCircle, Building2, Server } from 'lucide-react'; export default function WarehousesPage() { const [warehouses, setWarehouses] = useState([]); - const [newCode, setNewCode] = useState(''); + const [newId, setNewId] = useState(''); const [newName, setNewName] = useState(''); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); @@ -30,7 +30,7 @@ export default function WarehousesPage() { } } catch (error) { console.error(error); - showToast('خطا در دریافت لیست انبارها', true); + showToast('خطا در دریافت انبارها', true); } finally { setLoading(false); } @@ -46,12 +46,11 @@ export default function WarehousesPage() { }); if (res.ok) { setWarehouses(newWarehouses); - showToast('انبارها با موفقیت ذخیره شدند'); + showToast('لیست انبارها با موفقیت بروزرسانی شد'); } else { - showToast('خطا در ذخیره انبار', true); + showToast('خطا در ذخیره انبارها', true); } } catch (error) { - console.error(error); showToast('خطای شبکه', true); } finally { setSaving(false); @@ -59,33 +58,25 @@ export default function WarehousesPage() { }; const handleAdd = () => { - if (!newCode || !newName) { - showToast('لطفاً کد و نام انبار را وارد کنید', true); + if (!newId || !newName) { + showToast('لطفاً هم کد و هم نام انبار را وارد کنید', true); return; } - - // Convert to number strictly if Hesabfa requires int, but string is safer and compatible - const codeId = parseInt(newCode); - if(isNaN(codeId)) { - showToast('کد انبار باید عدد باشد', true); + if (warehouses.some(w => w.id === newId)) { + showToast('انباری با این کد قبلاً وجود دارد', true); return; } - - if (warehouses.find(w => parseInt(w.id) === codeId)) { - showToast('انباری با این کد قبلاً ثبت شده است', true); - return; - } - - const updated = [...warehouses, { id: codeId.toString(), name: newName }]; + const updated = [...warehouses, { id: newId, name: newName }]; saveWarehouses(updated); - setNewCode(''); + setNewId(''); setNewName(''); }; const handleDelete = (id) => { - if (!confirm('آیا از حذف این انبار اطمینان دارید؟')) return; - const updated = warehouses.filter(w => w.id !== id); - saveWarehouses(updated); + if (confirm('آیا از حذف این انبار اطمینان دارید؟')) { + const updated = warehouses.filter(w => w.id !== id); + saveWarehouses(updated); + } }; if (loading) { @@ -93,7 +84,7 @@ export default function WarehousesPage() {
-
+
); @@ -103,102 +94,110 @@ export default function WarehousesPage() {
-
-
-

انبارهای حسابفا

-

مدیریت لیست انبارهایی که سیستم استعلام موجودی می‌گیرد

+
+ +
+

+ + مدیریت انبارهای حسابفا +

+

+ کد انبار باید دقیقاً منطبق با کد انبار در سیستم حسابفا باشد. با افزودن انبار در اینجا، دسترسی کاربران به آن در اپلیکیشن فعال می‌شود. +

-
+ {/* Add New Warehouse */} +
+
-
-

-
- -
- ثبت انبار جدید -

- -
-
- - setNewCode(e.target.value)} - placeholder="مثال: 11" - className="w-full bg-white border border-gray-200 rounded-[12px] px-4 py-3 text-sm focus:outline-none focus:border-orange-500 transition-colors" - /> -
-
- - setNewName(e.target.value)} - placeholder="مثال: انبار مرکزی" - className="w-full bg-white border border-gray-200 rounded-[12px] px-4 py-3 text-sm focus:outline-none focus:border-orange-500 transition-colors" - /> -
- - {saving ?
: } - افزودن به لیست -
+

افزودن انبار جدید

+ +
+
+ setNewId(e.target.value)} + placeholder="کد حسابفا..." + className="w-28 bg-gray-50 border border-gray-200 rounded-[16px] px-4 py-3 text-sm font-bold focus:outline-none focus:border-indigo-500 focus:bg-white transition-all text-center placeholder:font-normal" + /> + setNewName(e.target.value)} + placeholder="نام انبار..." + className="flex-1 bg-gray-50 border border-gray-200 rounded-[16px] px-4 py-3 text-sm font-bold focus:outline-none focus:border-indigo-500 focus:bg-white transition-all placeholder:font-normal" + />
-
- -
-

لیست انبارهای فعال

- {warehouses.length === 0 ? ( -
-

هیچ انباری ثبت نشده است.

-
- ) : ( -
- - {warehouses.map((wh) => ( - -
-
- {wh.id} -
- {wh.name} -
- -
- ))} -
-
- )} + + + ثبت انبار در سیستم +
-
+ + {/* List of Warehouses */} +
+

لیست انبارهای فعال

+ + + {warehouses.map((wh) => ( + +
+
+ کد + {wh.id} +
+
+ {wh.name} + + متصل به حسابفا + +
+
+ + +
+ ))} +
+ + {warehouses.length === 0 && ( +
+ +

هیچ انباری تعریف نشده است.

+
+ )} +
+
+ {/* Toast Notification */} {toast.show && ( {toast.isError ? : } {toast.message} diff --git a/src/app/api/users/route.js b/src/app/api/users/route.js new file mode 100644 index 0000000..cb316ba --- /dev/null +++ b/src/app/api/users/route.js @@ -0,0 +1,60 @@ +import prisma from '@/lib/prisma'; +import { NextResponse } from 'next/server'; + +export async function GET() { + try { + const users = await prisma.user.findMany({ + select: { + id: true, + name: true, + username: true, + mobile: true, + roles: true, + role: true, + createdAt: true, + _count: { + select: { countings: true } + } + }, + orderBy: { createdAt: 'desc' } + }); + + // Parse roles + const parsedUsers = users.map(user => { + let parsedRoles = user.roles; + if (typeof parsedRoles === 'string') { + try { parsedRoles = JSON.parse(parsedRoles); } catch (e) { parsedRoles = null; } + } + return { + ...user, + roles: Array.isArray(parsedRoles) ? parsedRoles : (user.role === 'ADMIN' ? ['ADMIN'] : ['COUNTER']) + }; + }); + + return NextResponse.json(parsedUsers); + } catch (error) { + console.error('Fetch users error:', error); + return NextResponse.json({ error: 'خطا در دریافت کاربران' }, { status: 500 }); + } +} + +export async function PUT(req) { + try { + const { id, roles } = await req.json(); + + if (!id || !roles) { + return NextResponse.json({ error: 'اطلاعات ناقص است' }, { status: 400 }); + } + + const updated = await prisma.user.update({ + where: { id: parseInt(id) }, + data: { roles: JSON.stringify(roles) }, + select: { id: true, roles: true } + }); + + return NextResponse.json({ message: 'نقش‌های کاربر بروزرسانی شد', user: updated }); + } catch (error) { + console.error('Update user error:', error); + return NextResponse.json({ error: 'خطا در بروزرسانی کاربر' }, { status: 500 }); + } +}