PageSourceSearch

https://harbor-os.com/assets/AdminSponsoredStops-I8zAvV7R.js

js harbor-os.com collected 2026-10-02 01:34:22 UTC 18,316 bytes, 1 lines download raw bytes

1import{j as e,b as _,a_ as G,db as A,bD as R,r as g,g as L,i as S,e as W,G as N,bz as Y,fz as J,bA as y,_ as F,bU as X,bH as f}from"./vendor-B3bqREfz.js";import{T as Z,o as ee,p as v,r as C,u as $,I as p,g as c,B as j,D as K,h as U,j as z,k as H,m as O,f as w,q as k}from"./index-BHZdkTHk.js";import{A as se}from"./AdminLayout-C31anzfd.js";import{L as r}from"./label-USjEtjxC.js";import{S as T}from"./switch-CEyu8DAw.js";import{S as I,a as P,b as q,c as V,d as M}from"./select-CdK0CD7c.js";import{T as te}from"./textarea-BFtGXtJd.js";import"./harbor-shoppers-logo-BwiOLETu.js";function ae(){const{toast:o}=$(),[x,m]=g.useState(""),[n,l]=g.useState(null),[i,d]=g.useState({isSponsored:!1,sponsorTokenBonus:0,sponsorCampaignStart:"",sponsorCampaignEnd:""}),{data:a=[],isLoading:u}=L({queryKey:["/api/admin/sponsored-stops"],queryFn:async()=>{const s=await fetch("/api/admin/sponsored-stops",{credentials:"include"});if(!s.ok)throw new Error("Failed to load");return s.json()}}),t=S({mutationFn:s=>w("PUT",`/api/admin/sponsored-stops/${s}`,i),onSuccess:()=>{k.invalidateQueries({queryKey:["/api/admin/sponsored-stops"]}),o({title:"Marina updated"}),l(null)},onError:()=>o({title:"Update failed",variant:"destructive"})}),h=s=>{l(s),d({isSponsored:s.isSponsored??!1,sponsorTokenBonus:s.sponsorTokenBonus??0,sponsorCampaignStart:s.sponsorCampaignStart?new Date(s.sponsorCampaignStart).toISOString().slice(0,10):"",sponsorCampaignEnd:s.sponsorCampaignEnd?new Date(s.sponsorCampaignEnd).toISOString().slice(0,10):""})},b=a.filter(s=>{var B,D;return!x||((B=s.name)==null?void 0:B.toLowerCase().includes(x.toLowerCase()))||((D=s.region)==null?void 0:D.toLowerCase().includes(x.toLowerCase()))}),Q=b.filter(s=>s.isSponsored),E=b;return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsxs("div",{className:"relative flex-1 max-w-sm",children:[e.jsx(W,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400"}),e.jsx(p,{placeholder:"Search marinas…",value:x,onChange:s=>m(s.target.value),className:"pl-9"})]}),e.jsxs(c,{variant:"secondary",children:[Q.length," sponsored"]}),e.jsxs(c,{variant:"outline",children:[E.length," total"]})]}),u?e.jsx("div",{className:"flex items-center justify-center py-16",children:e.jsx(N,{className:"w-6 h-6 animate-spin text-teal-500"})}):e.jsx("div",{className:"overflow-x-auto rounded-xl border border-slate-200",children:e.jsxs("table",{className:"min-w-full text-sm",children:[e.jsx("thead",{className:"bg-slate-50 border-b border-slate-200",children:e.jsxs("tr",{children:[e.jsx("th",{className:"text-left px-4 py-2.5 font-medium text-slate-600",children:"Marina"}),e.jsx("th",{className:"text-left px-4 py-2.5 font-medium text-slate-600",children:"Region"}),e.jsx("th",{className:"text-center px-4 py-2.5 font-medium text-slate-600",children:"Sponsored"}),e.jsx("th",{className:"text-center px-4 py-2.5 font-medium text-slate-600",children:"Bonus ⚓"}),e.jsx("th",{className:"text-center px-4 py-2.5 font-medium text-slate-600",children:"Check-ins"}),e.jsx("th",{className:"text-center px-4 py-2.5 font-medium text-slate-600",children:"Campaign"}),e.jsx("th",{className:"text-center px-4 py-2.5 font-medium text-slate-600",children:"Actions"})]})}),e.jsx("tbody",{className:"divide-y divide-slate-100",children:E.map(s=>e.jsxs("tr",{className:`hover:bg-slate-50/50 transition-colors ${s.isSponsored?"bg-amber-50/30":""}`,children:[e.jsx("td",{className:"px-4 py-3 font-medium text-slate-800",children:e.jsxs("div",{className:"flex items-center gap-2",children:[s.isSponsored&&e.jsx(Y,{className:"w-3.5 h-3.5 text-amber-500 flex-shrink-0"}),s.name]})}),e.jsx("td",{className:"px-4 py-3 text-slate-500 text-xs",children:s.region||"—"}),e.jsx("td",{className:"px-4 py-3 text-center",children:s.isSponsored?e.jsx(c,{className:"bg-amber-100 text-amber-700 border-amber-200 text-xs",children:"Sponsored"}):e.jsx("span",{className:"text-slate-400 text-xs",children:"—"})}),e.jsx("td",{className:"px-4 py-3 text-center",children:s.sponsorTokenBonus>0?e.jsxs(c,{className:"bg-teal-100 text-teal-700 border-teal-200 text-xs",children:["+",s.sponsorTokenBonus]}):e.jsx("span",{className:"text-slate-400 text-xs",children:"—"})}),e.jsx("td",{className:"px-4 py-3 text-center text-slate-600 text-xs",children:s.sponsorCheckinCount??0}),e.jsx("td",{className:"px-4 py-3 text-center text-xs text-slate-500",children:s.sponsorCampaignStart||s.sponsorCampaignEnd?e.jsxs(e.Fragment,{children:[s.sponsorCampaignStart?new Date(s.sponsorCampaignStart).toLocaleDateString():"∞"," → ",s.sponsorCampaignEnd?new Date(s.sponsorCampaignEnd).toLocaleDateString():"∞"]}):"—"}),e.jsx("td",{className:"px-4 py-3 text-center",children:e.jsxs(j,{variant:"ghost",size:"sm",className:"h-7 px-2 text-xs",onClick:()=>h(s),children:[e.jsx(J,{className:"w-3.5 h-3.5 mr-1"}),"Edit"]})})]},s.id))})]})}),e.jsx(K,{open:!!n,onOpenChange:()=>l(null),children:e.jsxs(U,{className:"max-w-md",children:[e.jsx(z,{children:e.jsxs(H,{
1className:"flex items-center gap-2",children:[e.jsx(_,{className:"w-4 h-4 text-teal-500"}),n==null?void 0:n.name]})}),e.jsxs("div",{className:"space-y-4 py-2",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(r,{children:"Sponsored Stop"}),e.jsx(T,{checked:i.isSponsored,onCheckedChange:s=>d({...i,isSponsored:s})})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(r,{children:"Bonus Tokens on Check-in"}),e.jsx(p,{type:"number",min:"0",value:i.sponsorTokenBonus,onChange:s=>d({...i,sponsorTokenBonus:parseInt(s.target.value)||0}),placeholder:"e.g. 25"}),e.jsx("p",{className:"text-xs text-slate-500",children:"Added on top of the base check-in token award."})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(r,{children:"Campaign Start (optional)"}),e.jsx(p,{type:"date",value:i.sponsorCampaignStart,onChange:s=>d({...i,sponsorCampaignStart:s.target.value})})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(r,{children:"Campaign End (optional)"}),e.jsx(p,{type:"date",value:i.sponsorCampaignEnd,onChange:s=>d({...i,sponsorCampaignEnd:s.target.value})})]})]}),e.jsxs(O,{children:[e.jsx(j,{variant:"outline",onClick:()=>l(null),children:"Cancel"}),e.jsxs(j,{className:"bg-teal-600 hover:bg-teal-500 text-white",onClick:()=>t.mutate(n.id),disabled:t.isPending,children:[t.isPending?e.jsx(N,{className:"w-3.5 h-3.5 mr-1.5 animate-spin"}):e.jsx(y,{className:"w-3.5 h-3.5 mr-1.5"}),"Save"]})]})]})})]})}const ne=["listing_credit","featured_days","card_pack","mayor_lock","foil_card","pioneer_frame","topup_bonus"];function le(){const{toast:o}=$(),[x,m]=g.useState(!1),[n,l]=g.useState({category:"Marketplace",title:"",description:"",tokenCost:100,benefitType:"listing_credit",benefitValue:"",stockLimit:"",isActive:!0}),{data:i=[],isLoading:d}=L({queryKey:["/api/token-shop/items"],queryFn:async()=>{const t=await fetch("/api/token-shop/items",{credentials:"include"});return t.ok?(await t.json()).items??[]:[]}}),a=S({mutationFn:()=>w("POST","/api/admin/token-shop/items",n),onSuccess:()=>{k.invalidateQueries({queryKey:["/api/token-shop/items"]}),o({title:"Item created"}),m(!1),l({category:"Marketplace",title:"",description:"",tokenCost:100,benefitType:"listing_credit",benefitValue:"",stockLimit:"",isActive:!0})},onError:()=>o({title:"Failed to create item",variant:"destructive"})}),u=S({mutationFn:({id:t,isActive:h})=>w("PATCH",`/api/admin/token-shop/items/${t}`,{isActive:h}),onSuccess:()=>k.invalidateQueries({queryKey:["/api/token-shop/items"]})});return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-slate-800",children:"Shop Items"}),e.jsx("p",{className:"text-sm text-slate-500",children:"Manage redeemable items in the Harbor Token Shop."})]}),e.jsxs(j,{className:"bg-teal-600 hover:bg-teal-500 text-white text-xs h-8",onClick:()=>m(!0),children:[e.jsx(F,{className:"w-3.5 h-3.5 mr-1.5"}),"Add Item"]})]}),d?e.jsx("div",{className:"flex items-center justify-center py-16",children:e.jsx(N,{className:"w-6 h-6 animate-spin text-teal-500"})}):i.length===0?e.jsxs("div",{className:"text-center py-12 border border-dashed border-slate-300 rounded-xl",children:[e.jsx(A,{className:"w-10 h-10 text-slate-400 mx-auto mb-2"}),e.jsx("p",{className:"text-slate-500 text-sm",children:"No shop items yet. Add the first one!"})]}):e.jsx("div",{className:"overflow-x-auto rounded-xl border border-slate-200",children:e.jsxs("table",{className:"min-w-full text-sm",children:[e.jsx("thead",{className:"bg-slate-50 border-b border-slate-200",children:e.jsxs("tr",{children:[e.jsx("th",{className:"text-left px-4 py-2.5 font-medium text-slate-600",children:"Title"}),e.jsx("th",{className:"text-left px-4 py-2.5 font-medium text-slate-600",children:"Category"}),e.jsx("th",{className:"text-center px-4 py-2.5 font-medium text-slate-600",children:"Cost ⚓"}),e.jsx("th",{className:"text-left px-4 py-2.5 font-medium text-slate-600",children:"Benefit"}),e.jsx("th",{className:"text-center px-4 py-2.5 font-medium text-slate-600",children:"Stock"}),e.jsx("th",{className:"text-center px-4 py-2.5 font-medium text-slate-600",children:"Active"})]})}),e.jsx("tbody",{className:"divide-y divide-slate-100",children:i.map(t=>{var h;return e.jsxs("tr",{className:"hover:bg-slate-50/50 transition-colors",children:[e.jsx("td",{className:"px-4 py-3 font-medium text-slate-800",children:t.title}),e.jsx("td",{className:"px-4 py-3",children:e.jsx(c,{variant:"secondary",className:"text-xs",children:t.category})}),e.jsx("td",{className:"px-4 py-3 text-center",children:e.jsx(c,{className:"bg-teal-100 text-teal-700 border-teal-200 text-xs",children:(h=t.tokenCost)==null?void 0:h.toLocaleStr
1ing()})}),e.jsxs("td",{className:"px-4 py-3 text-slate-500 text-xs",children:[t.benefitType,t.benefitValue?` · ${t.benefitValue}`:""]}),e.jsx("td",{className:"px-4 py-3 text-center text-slate-500 text-xs",children:t.stockLimit??"∞"}),e.jsx("td",{className:"px-4 py-3 text-center",children:e.jsx(T,{checked:!!t.isActive,onCheckedChange:b=>u.mutate({id:t.id,isActive:b})})})]},t.id)})})]})}),e.jsx(K,{open:x,onOpenChange:m,children:e.jsxs(U,{className:"max-w-md",children:[e.jsx(z,{children:e.jsxs(H,{className:"flex items-center gap-2",children:[e.jsx(X,{className:"w-4 h-4 text-teal-500"}),"New Shop Item"]})}),e.jsxs("div",{className:"space-y-3 py-2",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(r,{children:"Category"}),e.jsxs(I,{value:n.category,onValueChange:t=>l({...n,category:t}),children:[e.jsx(P,{className:"h-8 text-xs",children:e.jsx(q,{})}),e.jsx(V,{children:["Marketplace","Collector","Community"].map(t=>e.jsx(M,{value:t,children:t},t))})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(r,{children:"Token Cost"}),e.jsx(p,{type:"number",min:"1",value:n.tokenCost,onChange:t=>l({...n,tokenCost:parseInt(t.target.value)||0}),className:"h-8 text-xs"})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(r,{children:"Title"}),e.jsx(p,{value:n.title,onChange:t=>l({...n,title:t.target.value}),className:"h-8 text-xs"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(r,{children:"Description"}),e.jsx(te,{value:n.description,onChange:t=>l({...n,description:t.target.value}),rows:2,className:"text-xs"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(r,{children:"Benefit Type"}),e.jsxs(I,{value:n.benefitType,onValueChange:t=>l({...n,benefitType:t}),children:[e.jsx(P,{className:"h-8 text-xs",children:e.jsx(q,{})}),e.jsx(V,{children:ne.map(t=>e.jsx(M,{value:t,children:t},t))})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(r,{children:"Benefit Value"}),e.jsx(p,{value:n.benefitValue,onChange:t=>l({...n,benefitValue:t.target.value}),className:"h-8 text-xs",placeholder:"optional"})]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(r,{children:"Stock Limit"}),e.jsx(p,{type:"number",min:"0",value:n.stockLimit,onChange:t=>l({...n,stockLimit:t.target.value}),className:"h-8 text-xs",placeholder:"unlimited"})]}),e.jsxs("div",{className:"flex items-center gap-2 pt-6",children:[e.jsx(T,{checked:n.isActive,onCheckedChange:t=>l({...n,isActive:t})}),e.jsx(r,{className:"text-xs",children:"Active"})]})]})]}),e.jsxs(O,{children:[e.jsx(j,{variant:"outline",onClick:()=>m(!1),children:"Cancel"}),e.jsxs(j,{className:"bg-teal-600 hover:bg-teal-500 text-white",onClick:()=>a.mutate(),disabled:a.isPending||!n.title,children:[a.isPending?e.jsx(N,{className:"w-3.5 h-3.5 mr-1.5 animate-spin"}):e.jsx(F,{className:"w-3.5 h-3.5 mr-1.5"}),"Create"]})]})]})})]})}function ie(){const[o,x]=g.useState("all"),m=o==="applied"?"?applied=true":o==="pending"?"?applied=false":"",{data:n=[],isLoading:l}=L({queryKey:["/api/admin/token-shop/redemptions",o],queryFn:async()=>{const a=await fetch(`/api/admin/token-shop/redemptions${m}`,{credentials:"include"});if(!a.ok)throw new Error("Failed to load");return a.json()}}),i=n.filter(a=>a.benefitApplied).length,d=n.filter(a=>!a.benefitApplied).length;return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-semibold text-slate-800",children:"Redemption Records"}),e.jsx("p",{className:"text-sm text-slate-500",children:"All token shop redemptions across all users."})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(c,{className:"bg-green-100 text-green-700 border-green-200 text-xs",children:[e.jsx(y,{className:"w-3 h-3 mr-1"}),i," applied"]}),e.jsxs(c,{className:"bg-amber-100 text-amber-700 border-amber-200 text-xs",children:[e.jsx(f,{className:"w-3 h-3 mr-1"}),d," pending"]})]})]}),e.jsx("div",{className:"flex gap-2 mb-3",children:["all","applied","pending"].map(a=>e.jsxs(j,{variant:o===a?"default":"outline",size:"sm",className:`text-xs h-7 capitalize ${o===a?"bg-teal-600 hover:bg-teal-500 text-white":""}`,onClick:()=>x(a),children:[a==="applied"&&e.jsx(y,{className:"w-3 h-3 mr-1"}),a==="pending"&&e.jsx(f,{className:"w-3 h-3 mr-1"}),a==="all"&&e.jsx(R,{className:"w-3 h-3 mr-1"}),a.charAt(0).toUpperCase()+a.slice(1)]},a))}),l?e.jsx("div",{className:"flex items-center justify-center py-16",children:e.jsx(N,{className:"w-6 h-6 animate-spin text-teal-500"})}):n.length===0?e.jsxs("div",{className:"text-center py-12 border border-dashed border-slate-300 rounded-xl",children:[e.jsx(A,{className:"w-10 h-10 text-slate-400 mx-auto mb-2"}),e.jsx("p",{className:"text-slate-500 text-sm",children:"No redemptions foun
1d."})]}):e.jsx("div",{className:"overflow-x-auto rounded-xl border border-slate-200",children:e.jsxs("table",{className:"min-w-full text-sm",children:[e.jsx("thead",{className:"bg-slate-50 border-b border-slate-200",children:e.jsxs("tr",{children:[e.jsx("th",{className:"text-left px-4 py-2.5 font-medium text-slate-600",children:"User"}),e.jsx("th",{className:"text-left px-4 py-2.5 font-medium text-slate-600",children:"Item"}),e.jsx("th",{className:"text-left px-4 py-2.5 font-medium text-slate-600",children:"Benefit"}),e.jsx("th",{className:"text-center px-4 py-2.5 font-medium text-slate-600",children:"Cost ⚓"}),e.jsx("th",{className:"text-center px-4 py-2.5 font-medium text-slate-600",children:"Redeemed"}),e.jsx("th",{className:"text-center px-4 py-2.5 font-medium text-slate-600",children:"Status"})]})}),e.jsx("tbody",{className:"divide-y divide-slate-100",children:n.map(a=>{var u;return e.jsxs("tr",{className:`hover:bg-slate-50/50 transition-colors ${a.benefitApplied?"":"bg-amber-50/20"}`,children:[e.jsxs("td",{className:"px-4 py-3",children:[e.jsx("p",{className:"font-medium text-slate-800 text-xs",children:a.username}),e.jsx("p",{className:"text-slate-400 text-[10px]",children:a.email})]}),e.jsxs("td",{className:"px-4 py-3",children:[e.jsx("p",{className:"text-slate-800 text-xs font-medium",children:a.title}),e.jsx(c,{variant:"secondary",className:"text-[10px] mt-0.5",children:a.category})]}),e.jsxs("td",{className:"px-4 py-3 text-slate-500 text-xs",children:[a.benefitType,a.benefitValue?` · ${a.benefitValue}`:""]}),e.jsx("td",{className:"px-4 py-3 text-center",children:e.jsx(c,{className:"bg-teal-100 text-teal-700 border-teal-200 text-xs",children:(u=a.tokenCost)==null?void 0:u.toLocaleString()})}),e.jsx("td",{className:"px-4 py-3 text-center text-slate-500 text-xs",children:new Date(a.redeemedAt).toLocaleDateString()}),e.jsx("td",{className:"px-4 py-3 text-center",children:a.benefitApplied?e.jsxs(c,{className:"bg-green-100 text-green-700 border-green-200 text-xs",children:[e.jsx(y,{className:"w-3 h-3 mr-1"}),"Applied"]}):e.jsxs(c,{className:"bg-amber-100 text-amber-700 border-amber-200 text-xs",children:[e.jsx(f,{className:"w-3 h-3 mr-1"}),"Pending"]})})]},a.id)})})]})})]})}function je(){return e.jsx(se,{children:e.jsxs("div",{className:"p-6 max-w-6xl mx-auto",children:[e.jsxs("div",{className:"mb-6",children:[e.jsxs("h1",{className:"text-xl font-bold text-slate-900 flex items-center gap-2",children:[e.jsx(_,{className:"w-5 h-5 text-teal-500"}),"Harbor World Admin"]}),e.jsx("p",{className:"text-slate-500 text-sm mt-1",children:"Manage sponsored marina stops and token shop items."})]}),e.jsxs(Z,{defaultValue:"sponsored",children:[e.jsxs(ee,{className:"bg-slate-100 border border-slate-200 rounded-xl p-1 mb-6",children:[e.jsxs(v,{value:"sponsored",className:"text-xs rounded-lg px-4 py-1.5 data-[state=active]:bg-white data-[state=active]:shadow-sm",children:[e.jsx(G,{className:"w-3.5 h-3.5 mr-1.5"}),"Sponsored Stops"]}),e.jsxs(v,{value:"shop-items",className:"text-xs rounded-lg px-4 py-1.5 data-[state=active]:bg-white data-[state=active]:shadow-sm",children:[e.jsx(A,{className:"w-3.5 h-3.5 mr-1.5"}),"Token Shop Items"]}),e.jsxs(v,{value:"redemptions",className:"text-xs rounded-lg px-4 py-1.5 data-[state=active]:bg-white data-[state=active]:shadow-sm",children:[e.jsx(R,{className:"w-3.5 h-3.5 mr-1.5"}),"Redemptions"]})]}),e.jsx(C,{value:"sponsored",children:e.jsx(ae,{})}),e.jsx(C,{value:"shop-items",children:e.jsx(le,{})}),e.jsx(C,{value:"redemptions",children:e.jsx(ie,{})})]})]})})}export{je as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.