PageSourceSearch

https://www.karispizza.fi/assets/CustomersPage-0e94a5ab.js

js karispizza.fi collected 2026-09-25 12:15:36 UTC 14,572 bytes, 1 lines download raw bytes

1import{j as e}from"./vendor-radix-0e72cabc.js";import{r as s}from"./vendor-react-9016e4a2.js";import{s as t,B as a,I as r,D as n,e as i,f as l,g as c,$ as d}from"./index-31192add.js";import{S as x,a as o,b as m,c as p,d as h}from"./select-dd5c609c.js";import{R as u,o as j,ay as v,c as N,U as f,ah as g,s as b,t as z,d as _}from"./vendor-icons-e8b10069.js";import{a as y,f as w}from"./vendor-date-225565b6.js";import"./vendor-supabase-36eb0853.js";import"./vendor-capacitor-43d743f6.js";import"./vendor-motion-a26fe6c4.js";const S=e=>`€${Number(e||0).toFixed(2)}`;function k(){const[k,C]=s.useState([]),[M,O]=s.useState(0),[I,$]=s.useState(1),[E,D]=s.useState(!0),[T,A]=s.useState(null),[q,B]=s.useState(""),[F,L]=s.useState("last_order"),[R,H]=s.useState(null),[P,U]=s.useState([]),[V,G]=s.useState([]),[J,K]=s.useState(!1),Q=s.useCallback(async()=>{D(!0),A(null);try{let e=t.from("orders").select("customer_name, customer_phone, user_id, restaurant_id, total_price, total_amount, status, created_at, restaurants(name)").not("customer_name","is",null).order("created_at",{ascending:!1});if(q.trim()){const s=q.trim().slice(0,100);e=e.ilike("customer_name",`%${s}%`)}const{data:s,error:a}=await e.limit(1e4);if(a)throw a;const r=new Map;for(const t of s||[]){const e=`${(t.customer_name||"").toLowerCase()}||${t.customer_phone||""}`,s=Number(t.total_price)||Number(t.total_amount)||0;r.has(e)||r.set(e,{key:e,name:t.customer_name||"—",phone:t.customer_phone||null,userId:t.user_id||null,orderCount:0,totalSpend:0,restaurants:new Set,firstOrder:t.created_at,lastOrder:t.created_at});const a=r.get(e);a.orderCount+=1,"completed"===t.status&&(a.totalSpend+=s),t.restaurants?.name&&a.restaurants.add(t.restaurants.name),!a.userId&&t.user_id&&(a.userId=t.user_id),t.created_at<a.firstOrder&&(a.firstOrder=t.created_at),t.created_at>a.lastOrder&&(a.lastOrder=t.created_at)}let n=Array.from(r.values()).map(e=>({...e,restaurants:Array.from(e.restaurants),loyalty:[],totalStamps:0}));const i=[...new Set(n.map(e=>e.userId).filter(Boolean))];if(i.length>0){const{data:e}=await t.from("customer_loyalty").select("customer_id, restaurant_id, stamps_count, total_stamps_earned, rewards_claimed, restaurants(name)").in("customer_id",i);if(e?.length){const s=new Map;for(const t of e)s.has(t.customer_id)||s.set(t.customer_id,[]),s.get(t.customer_id).push(t);n=n.map(e=>{const t=e.userId&&s.get(e.userId)||[];return{...e,loyalty:t,totalStamps:t.reduce((e,s)=>e+(s.stamps_count||0),0)}})}}"last_order"===F&&n.sort((e,s)=>s.lastOrder.localeCompare(e.lastOrder)),"order_count"===F&&n.sort((e,s)=>s.orderCount-e.orderCount),"total_spend"===F&&n.sort((e,s)=>s.totalSpend-e.totalSpend),"stamps"===F&&n.sort((e,s)=>s.totalStamps-e.totalStamps),O(n.length);const l=50*(I-1);C(n.slice(l,l+50))}catch(e){A(e.message)}finally{D(!1)}},[I,q,F]);s.useEffect(()=>{Q()},[Q]),s.useEffect(()=>{$(1)},[q,F]);const W=Math.ceil(M/50),X=k.length>0?(k.reduce((e,s)=>e+s.orderCount,0)/k.length).toFixed(1):0,Y=k.filter(e=>e.orderCount>1).length,Z=k.filter(e=>e.totalStamps>0).length;return e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-xl font-bold text-zinc-100",children:"Müşteriler"}),e.jsx("p",{className:"text-sm text-zinc-500 mt-0.5",children:"Platform genelinde tüm müşteriler"})]}),e.jsx(a,{variant:"outline",size:"sm",onClick:()=>Q(),disabled:E,className:"h-8 border-zinc-700 text-zinc-400 hover:text-zinc-100 hover:bg-zinc-800",children:e.jsx(u,{className:"h-3.5 w-3.5 "+(E?"animate-spin":"")})})]}),!E&&k.length>0&&e.jsxs("div",{className:"grid grid-cols-2 sm:grid-cols-4 gap-3",children:[e.jsxs("div",{className:"bg-zinc-900 border border-zinc-800 rounded-xl p-4",children:[e.jsx("div",{className:"text-[11px] text-zinc-500 uppercase tracking-widest mb-1",children:"Toplam Müşteri"}),e.jsx("div",{className:"text-xl font-bold text-zinc-100",children:M.toLocaleString("fi-FI")})]}),e.jsxs("div",{className:"bg-zinc-900 border border-zinc-800 rounded-xl p-4",children:[e.jsx("div",{className:"text-[11px] text-zinc-500 uppercase tracking-widest mb-1",children:"Tekrar Eden"}),e.jsx("div",{className:"text-xl font-bold text-emerald-400",children:Y}),e.jsx("div",{className:"text-xs text-zinc-600 mt-0.5",children:">1 sipariş"})]}),e.jsxs("div",{className:"bg-zinc-900 border border-zinc-800 rounded-xl p-4",children:[e.jsx("div",{className:"text-[11px] text-zinc-500 uppercase tracking-widest mb-1",children:"Ort. Sipariş"}),e.jsx("div",{className:"text-xl font-bold text-zinc-100",children:X})]}),e.jsxs("div",{className:"bg-zinc-900 border border-zinc-800 rounded-xl p-4",children:[e.jsx("div",{className:"text-[11px] text-zinc-500 uppercase tracking-widest mb-1",children:"Stamp Sahibi"}),e.jsx("div",{className:"text-xl font-bold text-amber-400",children:Z}),e.jsx("div",{className:"text-xs text-zinc-600 mt-0.5",children:"aktif stamp"})]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsx(j,{className:"absolute left-3 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-zinc-500"}),e.jsx(r,{placeholder:"İsim veya telefon ara…",value:q,onChange:e=>B(e.target.value),className:"pl-8 h-9 bg-zinc-900 border-zinc-700 text-zinc-200 placeholder:text-zinc-600 text-sm"}),q&&e.jsx("button",{onClick:()=>B(""),className:"absolute right-3 top-1/2 -translate-y-1/2 text-zinc-500 hover:text-zinc-300",children:e.jsx(v,{className:"h-3.5 w-3.5"})})]}),e.jsxs(x,{value:F,onValueChange:L,children:[e.jsx(o,{className:"w-48 h-9 bg-zinc-900 border-zinc-700 text-zinc-300 text-sm",children:e.jsx(m,{})}),e.jsxs(p,{className:"bg-zinc-900 border-zinc-700",children:[e.jsx(h,{value:"last_order",children:"Son sipariş"}),e.jsx(h,{value:"order_count",children:"En çok sipariş"}),e.jsx(h,{value:"total_spend",children:"En yüksek harcama"}),e.jsx(h,{value:"stamps",children:"En çok stamp"})]})]})]}),T&&e.jsxs("div",{className:"flex items-center gap-3 bg-red-500/10 border border-red-500/20 rounded-xl px-4 py-3 text-sm text-red-300",children:[e.jsx(N,{className:"h-4 w-4 shrink-0"})," ",T]}),e.jsxs("div",{className:"bg-zinc-900 border border-zinc-800 rounded-xl overflow-hidden",children:[e.jsxs("div",{className:"grid grid-cols-[1.5fr_1fr_70px_80px_90px_1fr_36px] gap-3 px-4 py-2.5 border-b border-zinc-800 text-[11px] font-semibold text-zinc-500 uppercase tracking-widest",children:[e.jsx("span",{children:"Müşteri"}),e.jsx("span",{children:"Telefon"}),e.jsx("span",{children:"Sipariş"}),e.jsx("span",{children:"Stamp"}),e.jsx("span",{children:"Harcama"}),e.jsx("span",{children:"Son Sipariş"}),e.jsx("span",{})]}),E?e.jsx("div",{className:"divide-y divide-zinc-800/60",children:Array.from({length:10},(s,t)=>e.jsxs("div",{className:"grid grid-cols-[1.5fr_1fr_70px_80px_90px_1fr_36px] gap-3 px-4 py-3",children:[[...Array(6)].map((s,t)=>e.jsx("div",{className:"h-4 bg-zinc-800 rounded animate-pulse"},t)),e.jsx("div",{})]},t))}):0===k.length?e.jsxs("div",{className:"py-16 text-center",children:[e.jsx(f,{className:"h-8 w-8 text-zinc-700 mx-auto mb-3"}),e.jsx("p",{className:"text-sm text-zinc-500",children:"Müşteri bulunamadı."})]}):e.jsx("div",{className:"divide-y divide-zinc-800/60",children:k.map(s=>e.jsxs("div",{className:"grid grid-cols-[1.5fr_1fr_70px_80px_90px_1fr_36px] gap-3 px-4 py-3 hover:bg-zinc-800/30 transition-colors items-center",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium text-zinc-200",children:s.name}),s.restaurants.length>0&&e.jsxs("div",{className:"text-[11px] text-zinc-600 truncate",children:[s.restaurants.slice(0,2).join(", "),s.restaurants.length>2&&" +"+(s.restaurants.length-2)]})]}),e.jsx("span",{className:"text-sm text-zinc-400",children:s.phone||"—"}),e.jsxs("div",{className:"text-center",children:[e.jsx("span",{className:"text-sm font-semibold "+(s.orderCount>3?"text-emerald-400":"text-zinc-300"),children:s.orderCount}),s.orderCount>1&&e.jsx("div",{className:"text-[10px] text-zinc-600",children:"tekrar"})]}),e.jsx("div",{className:"text-center",children:s.totalStamps>0?e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-center gap-1",children:[e.jsx(g,{className:"h-3 w-3 text-amber-400"}),e.jsx("span",{className:"text-sm font-semibold text-amber-400",children:s.totalStamps})]}),s.loyalty.length>1&&e.jsxs("div",{className:"text-[10px] text-zinc-600",children:[s.loyalty.length," resto"]})]}):e.jsx("span",{className:"text-zinc-700 text-sm",children:"—"})}),e.jsx("span",{className:"text-sm font-medium text-zinc-200",children:S(s.totalSpend)}),e.jsx("span",{className:"text-xs text-zinc-500",children:y(new Date(s.lastOrder),{addSuffix:!0})}),e.jsx("button",{onClick:()=>(async e=>{H(e),U([]),G(e.loyalty||[]),K(!0);try{const{data:s}=await t.from("orders").select("id, short_id, status, total_price, total_amount, created_at, order_type, restaurants(name)").ilike("customer_name",e.name).order("created_at",{ascending:!1}).limit(20);if(U(s||[]),e.userId){const{data:s}=await t.from("customer_loyalty").select("customer_id, restaurant_id, stamps_count, total_stamps_earned, rewards_claimed, restaurants(name, loyalty_stamps_required)").eq("customer_id",e.userId);G(s||[])}}finally{K(!1)}})(s),className:"text-zinc-600 hover:text-zinc-300 transition-colors",children:e.jsx(b,{className:"h-4 w-4"})})]},s.key))})]}),W>1&&e.jsxs("div",{className:"flex items-center justify-between text-sm text-zinc-500",children:[e.jsxs("span",{children:["Sayfa ",I," / ",W," · ",M.toLocaleStr
1ing()," müşteri"]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(a,{variant:"outline",size:"sm",onClick:()=>$(e=>Math.max(1,e-1)),disabled:1===I,className:"h-8 border-zinc-700 text-zinc-400 hover:bg-zinc-800",children:e.jsx(z,{className:"h-4 w-4"})}),e.jsx(a,{variant:"outline",size:"sm",onClick:()=>$(e=>Math.min(W,e+1)),disabled:I===W,className:"h-8 border-zinc-700 text-zinc-400 hover:bg-zinc-800",children:e.jsx(_,{className:"h-4 w-4"})})]})]}),e.jsx(n,{open:!!R,onOpenChange:e=>!e&&H(null),children:e.jsxs(i,{className:"bg-zinc-900 border-zinc-800 text-zinc-100 max-w-lg max-h-[90vh] overflow-y-auto",children:[e.jsxs(l,{children:[e.jsx(c,{className:"text-zinc-100",children:R?.name}),e.jsxs(d,{className:"text-zinc-500",children:[R?.phone||"Telefon yok"," · ",R?.orderCount," sipariş · ",S(R?.totalSpend)," toplam"]})]}),e.jsxs("div",{className:"space-y-4 text-sm",children:[e.jsxs("div",{className:"grid grid-cols-4 gap-2",children:[e.jsxs("div",{className:"bg-zinc-800/50 rounded-lg p-3 text-center",children:[e.jsx("div",{className:"text-[10px] text-zinc-500 uppercase tracking-wider",children:"Siparişler"}),e.jsx("div",{className:"text-lg font-bold text-zinc-100 mt-1",children:R?.orderCount})]}),e.jsxs("div",{className:"bg-zinc-800/50 rounded-lg p-3 text-center",children:[e.jsx("div",{className:"text-[10px] text-zinc-500 uppercase tracking-wider",children:"Harcama"}),e.jsx("div",{className:"text-lg font-bold text-emerald-400 mt-1",children:S(R?.totalSpend)})]}),e.jsxs("div",{className:"bg-zinc-800/50 rounded-lg p-3 text-center",children:[e.jsx("div",{className:"text-[10px] text-zinc-500 uppercase tracking-wider",children:"Restoranlar"}),e.jsx("div",{className:"text-lg font-bold text-zinc-100 mt-1",children:R?.restaurants?.length||0})]}),e.jsxs("div",{className:"bg-zinc-800/50 rounded-lg p-3 text-center",children:[e.jsx("div",{className:"text-[10px] text-zinc-500 uppercase tracking-wider",children:"Stamp"}),e.jsx("div",{className:"text-lg font-bold mt-1 "+(R?.totalStamps>0?"text-amber-400":"text-zinc-600"),children:R?.totalStamps||0})]})]}),e.jsxs("div",{className:"text-xs text-zinc-600",children:["İlk sipariş: ",R?.firstOrder?w(new Date(R.firstOrder),"dd.MM.yyyy"):"—"," · ","Son sipariş: ",R?.lastOrder?w(new Date(R.lastOrder),"dd.MM.yyyy"):"—"]}),J?null:V.length>0?e.jsxs("div",{children:[e.jsxs("div",{className:"text-[11px] text-zinc-500 uppercase tracking-widest font-semibold mb-2 flex items-center gap-1.5",children:[e.jsx(g,{className:"h-3 w-3"})," Sadakat Stampleri"]}),e.jsx("div",{className:"space-y-2",children:V.map((s,t)=>{const a=s.restaurants?.loyalty_stamps_required||10,r=Math.min(100,Math.round((s.stamps_count||0)/a*100));return e.jsxs("div",{className:"bg-zinc-800/50 rounded-lg p-3",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-xs font-medium text-zinc-200",children:s.restaurants?.name||`Restoran #${s.restaurant_id}`}),e.jsxs("div",{className:"flex items-center gap-2 text-xs text-zinc-400",children:[e.jsx("span",{className:"text-amber-400 font-semibold",children:s.stamps_count||0}),e.jsxs("span",{className:"text-zinc-600",children:["/ ",a," stamp"]})]})]}),e.jsx("div",{className:"h-1.5 bg-zinc-700 rounded-full overflow-hidden",children:e.jsx("div",{className:"h-full bg-amber-400 rounded-full transition-all",style:{width:`${r}%`}})}),e.jsxs("div",{className:"flex items-center justify-between mt-1.5 text-[10px] text-zinc-600",children:[e.jsxs("span",{children:["Toplam kazanılan: ",s.total_stamps_earned||0]}),e.jsxs("span",{children:["Ödül kullanılan: ",s.rewards_claimed||0]})]})]},t)})})]}):R?.userId?e.jsx("div",{className:"text-xs text-zinc-600 text-center py-2",children:"Bu müşterinin stamp kaydı yok."}):e.jsx("div",{className:"text-xs text-zinc-600 text-center py-2",children:"Misafir olarak sipariş vermiş — stamp verisi yok."}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] text-zinc-500 uppercase tracking-widest font-semibold mb-2",children:"Son Siparişler"}),J?e.jsx("div",{className:"space-y-2",children:[1,2,3].map(s=>e.jsx("div",{className:"h-10 bg-zinc-800 rounded animate-pulse"},s))}):e.jsx("div",{className:"space-y-1 max-h-48 overflow-y-auto",children:P.map(s=>e.jsxs("div",{className:"flex items-center justify-between py-1.5 px-2 rounded-lg bg-zinc-800/50 text-xs",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-zinc-300 font-medium",children:s.restaurants?.name}),e.jsx("span",{className:"text-zinc-600 ml-2",children:w(new Date(s.created_at),"dd.MM.yyyy")})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-[10px] px-1.5 py-0.5 rounded-full "+("completed"===s.status?"bg-emerald-500/15 text-emerald-400":"cancelled"===s.status?"bg-red-500/15 text-red-400":"bg-zinc-700 text-zinc-400"),children:s.status}),e.jsx("span",{className:"text-zinc-300",children:S(Number(s.total_price)||Number(s.total_amount)||0)})]})]},s.id))})]})]})]})})]})}export{k 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.