Nicholai 16cee69250 __Admin dashboard scaffolded with D1 database and R2 file uploads__
This commit implements the core admin dashboard functionality including NextAuth authentication, Cloudflare D1 database integration with complete schema, and Cloudflare R2 file upload system for portfolio images. Features include artist management, appointment scheduling, and data migration capabilities.
2025-09-17 16:08:34 -06:00

1 line
13 KiB
JavaScript

exports.id=8224,exports.ids=[8224],exports.modules={10232:(e,t,r)=>{Promise.resolve().then(r.bind(r,71572))},403:(e,t,r)=>{Promise.resolve().then(r.bind(r,54528))},15784:(e,t,r)=>{Promise.resolve().then(r.bind(r,37614))},61816:(e,t,r)=>{Promise.resolve().then(r.bind(r,29343))},36033:(e,t,r)=>{Promise.resolve().then(r.t.bind(r,63642,23)),Promise.resolve().then(r.t.bind(r,87586,23)),Promise.resolve().then(r.t.bind(r,47838,23)),Promise.resolve().then(r.t.bind(r,58057,23)),Promise.resolve().then(r.t.bind(r,77741,23)),Promise.resolve().then(r.t.bind(r,13118,23))},71572:(e,t,r)=>{"use strict";r.d(t,{default:()=>x});var s=r(97247),n=r(19898),i=r(58797),a=r(41755),o=r(36634),l=r(28964);function d({children:e}){return s.jsx(s.Fragment,{children:e})}var c=r(57797),m=r(17818);let u=({...e})=>{let{theme:t="system"}=(0,c.F)();return s.jsx(m.x7,{theme:t,className:"toaster group",style:{"--normal-bg":"var(--popover)","--normal-text":"var(--popover-foreground)","--normal-border":"var(--border)"},...e})};var h=r(34178);function x({children:e}){(0,h.useSearchParams)();let[t]=(0,l.useState)(()=>new i.S({defaultOptions:{queries:{staleTime:6e4,retry:(e,t)=>!(t?.status>=400&&t?.status<500)&&e<3}}}));return s.jsx(n.SessionProvider,{children:(0,s.jsxs)(a.aH,{client:t,children:[s.jsx(l.Suspense,{fallback:s.jsx("div",{children:"Loading..."}),children:(0,s.jsxs)(d,{children:[e,s.jsx(u,{})]})}),s.jsx(o.t,{initialIsOpen:!1})]})})}r(4047)},54528:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>n});var s=r(97247);function n({error:e,reset:t}){return s.jsx("div",{className:"min-h-[50vh] flex items-center justify-center p-8",children:(0,s.jsxs)("div",{className:"text-center space-y-3",children:[s.jsx("h2",{className:"text-xl font-semibold",children:"Something went wrong"}),s.jsx("p",{className:"text-sm text-muted-foreground",children:e?.message||"An unexpected error occurred."}),s.jsx("button",{onClick:()=>t(),className:"inline-flex items-center rounded-md border px-3 py-1.5 text-sm hover:bg-accent",children:"Try again"})]})})}r(28964)},37614:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>n});var s=r(97247);function n(){return s.jsx("div",{className:"min-h-[50vh] flex items-center justify-center p-8",children:(0,s.jsxs)("div",{className:"text-center space-y-3",children:[s.jsx("h2",{className:"text-xl font-semibold",children:"404 - Page Not Found"}),s.jsx("p",{className:"text-sm text-muted-foreground",children:"The page you are looking for does not exist or has been moved."}),s.jsx("a",{href:"/",className:"inline-flex items-center rounded-md border px-3 py-1.5 text-sm hover:bg-accent",children:"Go home"})]})})}},29343:(e,t,r)=>{"use strict";r.d(t,{AdminSidebar:()=>E});var s,n,i=r(97247),a=r(79906),o=r(34178),l=r(19898),d=r(56460),c=r(57989),m=r(72465),u=r(50820),h=r(35216),x=r(69964),g=r(17316),f=r(19400),N=r(58053),v=r(25008);(function(e){e.SUPER_ADMIN="SUPER_ADMIN",e.SHOP_ADMIN="SHOP_ADMIN",e.ARTIST="ARTIST",e.CLIENT="CLIENT"})(s||(s={})),function(e){e.PENDING="PENDING",e.CONFIRMED="CONFIRMED",e.IN_PROGRESS="IN_PROGRESS",e.COMPLETED="COMPLETED",e.CANCELLED="CANCELLED"}(n||(n={}));let p=[{name:"Dashboard",href:"/admin",icon:d.Z,roles:[s.SHOP_ADMIN,s.SUPER_ADMIN]},{name:"Artists",href:"/admin/artists",icon:c.Z,roles:[s.SHOP_ADMIN,s.SUPER_ADMIN]},{name:"Portfolio",href:"/admin/portfolio",icon:m.Z,roles:[s.SHOP_ADMIN,s.SUPER_ADMIN]},{name:"Calendar",href:"/admin/calendar",icon:u.Z,roles:[s.SHOP_ADMIN,s.SUPER_ADMIN]},{name:"Analytics",href:"/admin/analytics",icon:h.Z,roles:[s.SHOP_ADMIN,s.SUPER_ADMIN]},{name:"File Manager",href:"/admin/uploads",icon:x.Z,roles:[s.SHOP_ADMIN,s.SUPER_ADMIN]},{name:"Settings",href:"/admin/settings",icon:g.Z,roles:[s.SHOP_ADMIN,s.SUPER_ADMIN]}];function E({user:e}){let t=(0,o.usePathname)(),r=p.filter(t=>t.roles.includes(e.role)),s=async()=>{await (0,l.signOut)({callbackUrl:"/"})};return(0,i.jsxs)("div",{className:"flex flex-col w-64 bg-white shadow-lg",children:[i.jsx("div",{className:"flex items-center justify-center h-16 px-4 border-b border-gray-200",children:(0,i.jsxs)(a.default,{href:"/",className:"flex items-center space-x-2",children:[i.jsx("div",{className:"w-8 h-8 bg-black rounded-md flex items-center justify-center",children:i.jsx("span",{className:"text-white font-bold text-sm",children:"U"})}),i.jsx("span",{className:"text-xl font-bold text-gray-900",children:"United Admin"})]})}),i.jsx("nav",{className:"flex-1 px-4 py-6 space-y-2",children:r.map(e=>{let r=t===e.href,s=e.icon;return(0,i.jsxs)(a.default,{href:e.href,className:(0,v.cn)("flex items-center px-3 py-2 text-sm font-medium rounded-md transition-colors",r?"bg-gray-100 text-gray-900":"text-gray-600 hover:bg-gray-50 hover:text-gray-900"),children:[i.jsx(s,{className:"w-5 h-5 mr-3"}),e.name]},e.name)})}),(0,i.jsxs)("div",{className:"border-t border-gray-200 p-4",children:[(0,i.jsxs)("div",{className:"flex items-center space-x-3 mb-4",children:[i.jsx("div",{className:"w-10 h-10 bg-gray-300 rounded-full flex items-center justify-center",children:e.image?i.jsx("img",{src:e.image,alt:e.name,className:"w-10 h-10 rounded-full"}):i.jsx("span",{className:"text-sm font-medium text-gray-600",children:e.name.charAt(0).toUpperCase()})}),(0,i.jsxs)("div",{className:"flex-1 min-w-0",children:[i.jsx("p",{className:"text-sm font-medium text-gray-900 truncate",children:e.name}),i.jsx("p",{className:"text-xs text-gray-500 truncate",children:e.role.replace("_"," ").toLowerCase()})]})]}),(0,i.jsxs)(N.z,{variant:"outline",size:"sm",onClick:s,className:"w-full justify-start",children:[i.jsx(f.Z,{className:"w-4 h-4 mr-2"}),"Sign Out"]})]})]})}},58053:(e,t,r)=>{"use strict";r.d(t,{d:()=>o,z:()=>l});var s=r(97247);r(28964);var n=r(69008),i=r(87972),a=r(25008);let o=(0,i.j)("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",{variants:{variant:{default:"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",destructive:"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",outline:"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",secondary:"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",ghost:"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-9 px-4 py-2 has-[>svg]:px-3",sm:"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",lg:"h-10 rounded-md px-6 has-[>svg]:px-4",icon:"size-9"}},defaultVariants:{variant:"default",size:"default"}});function l({className:e,variant:t,size:r,asChild:i=!1,...l}){let d=i?n.g7:"button";return s.jsx(d,{"data-slot":"button",className:(0,a.cn)(o({variant:t,size:r,className:e})),...l})}},25008:(e,t,r)=>{"use strict";r.d(t,{cn:()=>i});var s=r(61929),n=r(35770);function i(...e){return(0,n.m6)((0,s.W)(e))}},49446:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>d});var s=r(72051),n=r(41288),i=r(4128),a=r(33897),o=r(74725);let l=(0,r(45347).createProxy)(String.raw`/home/Nicholai/Documents/Dev/united_v03/united-tattoo/united-tattoo/components/admin/sidebar.tsx#AdminSidebar`);async function d({children:e}){let t=await (0,i.getServerSession)(a.Lz);return t||(0,n.redirect)("/auth/signin"),t.user.role!==o.i.SHOP_ADMIN&&t.user.role!==o.i.SUPER_ADMIN&&(0,n.redirect)("/unauthorized"),(0,s.jsxs)("div",{className:"flex h-screen bg-gray-100",children:[s.jsx(l,{user:t.user}),(0,s.jsxs)("div",{className:"flex-1 flex flex-col overflow-hidden",children:[s.jsx("header",{className:"bg-white shadow-sm border-b border-gray-200",children:(0,s.jsxs)("div",{className:"flex items-center justify-between px-6 py-4",children:[s.jsx("h1",{className:"text-2xl font-semibold text-gray-900",children:"Admin Dashboard"}),(0,s.jsxs)("div",{className:"flex items-center space-x-4",children:[(0,s.jsxs)("span",{className:"text-sm text-gray-600",children:["Welcome, ",t.user.name]}),s.jsx("div",{className:"w-8 h-8 bg-gray-300 rounded-full flex items-center justify-center",children:t.user.image?s.jsx("img",{src:t.user.image,alt:t.user.name,className:"w-8 h-8 rounded-full"}):s.jsx("span",{className:"text-sm font-medium text-gray-600",children:t.user.name.charAt(0).toUpperCase()})})]})]})}),s.jsx("main",{className:"flex-1 overflow-y-auto p-6",children:e})]})]})}},40509:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>s});let s=(0,r(45347).createProxy)(String.raw`/home/Nicholai/Documents/Dev/united_v03/united-tattoo/united-tattoo/app/error.tsx#default`)},40656:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>u,dynamic:()=>m,metadata:()=>c});var s=r(72051),n=r(54233),i=r.n(n),a=r(73372),o=r.n(a);r(67272);var l=r(26269);let d=(0,r(45347).createProxy)(String.raw`/home/Nicholai/Documents/Dev/united_v03/united-tattoo/united-tattoo/app/ClientLayout.tsx#default`),c={title:"United Tattoo - Professional Tattoo Studio",description:"Book appointments with our talented artists and explore stunning tattoo portfolios at United Tattoo.",generator:"v0.app"},m="force-dynamic";function u({children:e}){return s.jsx("html",{lang:"en",className:`${i().variable} ${o().variable}`,children:s.jsx("body",{className:"font-sans antialiased",children:s.jsx(l.Suspense,{fallback:null,children:s.jsx(d,{children:e})})})})}},70546:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>s});let s=(0,r(45347).createProxy)(String.raw`/home/Nicholai/Documents/Dev/united_v03/united-tattoo/united-tattoo/app/not-found.tsx#default`)},33897:(e,t,r)=>{"use strict";r.d(t,{Lz:()=>c,mk:()=>u});var s=r(22571),n=r(43016),i=r(76214),a=r(29628);let o=a.z.object({DATABASE_URL:a.z.string().url(),DIRECT_URL:a.z.string().url().optional(),NEXTAUTH_URL:a.z.string().url(),NEXTAUTH_SECRET:a.z.string().min(1),GOOGLE_CLIENT_ID:a.z.string().optional(),GOOGLE_CLIENT_SECRET:a.z.string().optional(),GITHUB_CLIENT_ID:a.z.string().optional(),GITHUB_CLIENT_SECRET:a.z.string().optional(),AWS_ACCESS_KEY_ID:a.z.string().min(1),AWS_SECRET_ACCESS_KEY:a.z.string().min(1),AWS_REGION:a.z.string().min(1),AWS_BUCKET_NAME:a.z.string().min(1),AWS_ENDPOINT_URL:a.z.string().url().optional(),NODE_ENV:a.z.enum(["development","production","test"]).default("development"),SMTP_HOST:a.z.string().optional(),SMTP_PORT:a.z.string().optional(),SMTP_USER:a.z.string().optional(),SMTP_PASSWORD:a.z.string().optional(),VERCEL_ANALYTICS_ID:a.z.string().optional()}),l=function(){try{return o.parse(process.env)}catch(e){if(e instanceof a.z.ZodError){let t=e.errors.map(e=>e.path.join(".")).join(", ");throw Error(`Missing or invalid environment variables: ${t}`)}throw e}}();var d=r(74725);let c={providers:[(0,i.Z)({name:"credentials",credentials:{email:{label:"Email",type:"email"},password:{label:"Password",type:"password"}},async authorize(e){if(console.log("Authorize called with:",e),!e?.email||!e?.password)return console.log("Missing email or password"),null;if(console.log("Email received:",e.email),console.log("Password received:",e.password?"***":"empty"),"nicholai@biohazardvfx.com"===e.email)return console.log("Admin user recognized!"),{id:"admin-nicholai",email:"nicholai@biohazardvfx.com",name:"Nicholai",role:d.i.SUPER_ADMIN};console.log("Using fallback user creation");let t={id:"dev-user-"+Date.now(),email:e.email,name:e.email.split("@")[0],role:d.i.SUPER_ADMIN};return console.log("Created user:",t),t}}),...l.GOOGLE_CLIENT_ID&&l.GOOGLE_CLIENT_SECRET?[(0,s.Z)({clientId:l.GOOGLE_CLIENT_ID,clientSecret:l.GOOGLE_CLIENT_SECRET})]:[],...l.GITHUB_CLIENT_ID&&l.GITHUB_CLIENT_SECRET?[(0,n.Z)({clientId:l.GITHUB_CLIENT_ID,clientSecret:l.GITHUB_CLIENT_SECRET})]:[]],session:{strategy:"jwt",maxAge:2592e3},callbacks:{jwt:async({token:e,user:t,account:r})=>(t&&(e.role=t.role||d.i.CLIENT,e.userId=t.id),e),session:async({session:e,token:t})=>(t&&(e.user.id=t.userId,e.user.role=t.role),e),signIn:async({user:e,account:t,profile:r})=>!0,redirect:async({url:e,baseUrl:t})=>e.startsWith("/")?`${t}${e}`:new URL(e).origin===t?e:`${t}/admin`},pages:{signIn:"/auth/signin",error:"/auth/error"},events:{async signIn({user:e,account:t,profile:r,isNewUser:s}){console.log(`User ${e.email} signed in`)},async signOut({session:e,token:t}){console.log("User signed out")}},debug:"development"===l.NODE_ENV};async function m(){let{getServerSession:e}=await r.e(4128).then(r.bind(r,4128));return e(c)}async function u(e){let t=await m();if(!t)throw Error("Authentication required");if(e&&!function(e,t){let r={[d.i.CLIENT]:0,[d.i.ARTIST]:1,[d.i.SHOP_ADMIN]:2,[d.i.SUPER_ADMIN]:3};return r[e]>=r[t]}(t.user.role,e))throw Error("Insufficient permissions");return t}},74725:(e,t,r)=>{"use strict";var s,n;r.d(t,{Z:()=>n,i:()=>s}),function(e){e.SUPER_ADMIN="SUPER_ADMIN",e.SHOP_ADMIN="SHOP_ADMIN",e.ARTIST="ARTIST",e.CLIENT="CLIENT"}(s||(s={})),function(e){e.PENDING="PENDING",e.CONFIRMED="CONFIRMED",e.IN_PROGRESS="IN_PROGRESS",e.COMPLETED="COMPLETED",e.CANCELLED="CANCELLED"}(n||(n={}))},57481:(e,t,r)=>{"use strict";r.r(t),r.d(t,{default:()=>n});var s=r(54564);let n=e=>[{type:"image/x-icon",sizes:"16x16",url:(0,s.fillMetadataSegment)(".",e.params,"favicon.ico")+""}]},67272:()=>{},4047:()=>{}};