PageSourceSearch

https://joyfulwines.no/assets/admin.portal-DBdpMf45.js

js joyfulwines.no collected 2026-10-09 22:02:38 UTC 16,769 bytes, 1 lines download raw bytes

1import{c as v,a as _,b as y,d as A,r as p,j as e}from"./index-DTqmWzoE.js";import{u as g}from"./useServerFn-BynEDteX.js";import{u as R}from"./useQuery-64M4z5ah.js";const M=v({method:"GET"}).middleware([_]).handler(y("c58fd61df0f5e92d2b58d4d4edcf192c73d047ed30d0e714b897e971a5a366bf")),V=v({method:"POST"}).middleware([_]).handler(y("fccd48f26d6e95ff05822fab8babaa86163b7693abe5258ced27da3856634017")),E=v({method:"POST"}).middleware([_]).handler(y("f3586a363f1576787657551c747970265eeb0443478579e0c2431cc6db731893")),D=v({method:"POST"}).middleware([_]).handler(y("366691e1502050317be9588cade2280e30af3eff09e0fed278c18c0461f78201")),B=v({method:"POST"}).middleware([_]).handler(y("1bc7f210a2d393f3a0878b009687c83b2c4a9954c126662fb431f254f9371ef4")),q=v({method:"POST"}).middleware([_]).handler(y("bf57da3eb2ec7edab4265a2ddca27d01aa89cbf6c9979d92df64f13233242c66")),K=v({method:"POST"}).middleware([_]).handler(y("6d705a665789ba7f1853080c220d57efa37f103b5cf63f29f0b2690e6bba7782")),I=v({method:"POST"}).middleware([_]).handler(y("cdb0db0d318e982ae1c188058aaf10910fab2e0e75ed30c5718e878404507575")),U={event:"Arrangementer",shop_product:"Butikkprodukter",wine:"Viner",wine_trip:"Vinreiser",wine_club:"Vinklubb"};function ee(){const s=g(M),i=A(),{data:c,isLoading:h}=R({queryKey:["portal-overview"],queryFn:()=>s()}),[l,a]=p.useState("settings"),t=()=>i.invalidateQueries({queryKey:["portal-overview"]});return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("header",{children:[e.jsx("h2",{className:"font-serif text-xl text-[#3d3225]",children:"Vipps Portal"}),e.jsx("p",{className:"mt-1 text-sm text-[#8b7355]",children:"Frittstående forberedelse av betalingsportalen (bankkonto, mva og regnskap). Ingenting her påvirker dagens Vipps-betalinger — de fortsetter uendret til vi aktivt skrur på ny løsning."})]}),e.jsx("nav",{className:"flex flex-wrap gap-2",children:[["settings","Innstillinger"],["companies","Firmaer"],["products","Produkter & arrangementer"],["log","Logg"]].map(([r,d])=>e.jsx("button",{onClick:()=>a(r),className:`rounded-full px-4 py-1.5 text-sm ${l===r?"bg-[#8b7355] text-white":"bg-white/70 text-[#6f5b41] ring-1 ring-[#e6dfd1]"}`,children:d},r))}),h&&e.jsx("p",{className:"text-sm text-[#8b7355]",children:"Laster…"}),c&&l==="settings"&&e.jsx(H,{data:c,onDone:t}),c&&l==="companies"&&e.jsx(Q,{data:c,onDone:t}),c&&l==="products"&&e.jsx(J,{data:c,onDone:t}),c&&l==="log"&&e.jsx(Y,{data:c})]})}function N({title:s,children:i}){return e.jsxs("section",{className:"space-y-4 rounded-2xl bg-white/70 p-5 ring-1 ring-[#e6dfd1]",children:[s&&e.jsx("h3",{className:"font-serif text-lg text-[#3d3225]",children:s}),i]})}function x({label:s,children:i}){return e.jsxs("label",{className:"block",children:[e.jsx("span",{className:"mb-1 block text-xs uppercase tracking-wide text-[#8b7355]",children:s}),i]})}const m="w-full rounded-full border border-[#d8cdb8] bg-white px-3 py-1.5 text-sm",$="jw_portal_settings_draft_v1";function H({data:s,onDone:i}){const c=g(V),h=g(K),l=g(q),a=s.settings??{},[t,r]=p.useState({enabled:!!a.enabled,environment:a.environment??"test",base_url:a.base_url??"https://pay-connect-central.lovable.app/api/public/v1",api_key:a.api_key??"",webhook_secret:a.webhook_secret??"",return_url:a.return_url??"",webhook_url:a.webhook_url??"",default_company_id:a.default_company_id??"",default_vat_code:a.default_vat_code??"25",notes:a.notes??""}),[d,n]=p.useState(!1),k=typeof window<"u"?window.location.origin:"",[u,b]=p.useState(null),[f,w]=p.useState(null),[P,F]=p.useState(!1);p.useEffect(()=>{try{const o=window.localStorage.getItem($);if(o){const C=JSON.parse(o);r(j=>({...j,...C}))}}catch{}F(!0)},[]),p.useEffect(()=>{if(P)try{window.localStorage.setItem($,JSON.stringify(t))}catch{}},[P,t]);async function S(o,C){w(o),b(null);try{const j=await C();b(o==="import"?`Import fullført: ${Object.entries(j.counts??{}).map(([L,O])=>`${L}: ${O}`).join(", ")}`:o==="test"?`Tilkobling OK ${j.title??""} ${j.version??""}`:"Lagret ✓"),i()}catch(j){b(`Feil: ${j?.message??j}`)}finally{w(null)}}async function T(){return await c({data:t}),h()}return e.jsxs("div",{className:"space-y-6",children:[e.jsx(N,{title:"Status",children:e.jsxs("div",{className:"flex flex-wrap items-center gap-3 text-sm",children:[e.jsx("span",{className:`rounded-full px-3 py-1 text-xs ${t.enabled?"bg-[#2f6b46] text-white":"bg-[#f0e9dc] text-[#8b7355]"}`,children:t.enabled?"Portal aktivert":"Portal av (dagens Vipps-løsning brukes)"}),e.jsxs("span",{className:"text-xs text-[#8b7355]",children:["API-nøkkel: ",t.api_key?"lagret i innstillinger ✓":s.hasApiKey?"lagret som prosjekt-secret ✓":"mangler"]})]})}),e.jsxs(N,{title:"Tilkobling",children:[e.jsx(x,{label:"API-adresse (base URL)",children:e.jsx("input",{value:t.base_url,onChange:o=>r({...t,base_url:o.target.value.trim()}),placeholder:"https://pay-connect-central.lovable.app/api/public/v1",name:"portal-base-url",autoComplete:"off","data-1p-ignore":!0,"data-lpignore":"true","data-form-type":"other",className:`${m} font-mono`})}),e.jsx(x,{label:"API-nøkkel (sk_test_… / sk_live_…)",children:e.jsx("input",{value:t.api_key,onChange:o=>r({...t,api_key:o.target.value.trim()}),type:d?"text":"password",placeholder:"sk_test_…",name:"portal-api-key",autoComplete:"new-password","data-1p-ignore":!0,"data-lpignore":"true","data-form-type":"other",className:`${m} font-mono`})}),e.jsxs("p",{className:"text-xs text-[#8b7355]",children:["Hentes i portalen under Innstillinger → API-klienter (vises kun én gang). Sendes som header ",e.jsx("code",{className:"font-mono",children:"x-api-key"}),"."]}),e.jsx(x,{label:"Webhook-signeringsnøkkel",children:e.jsx("input",{value:t.webhook_secret,onChange:o=>r({...t,webhook_secret:o.target.value.trim()}),type:d?"text":"password",placeholder:"fra Innstillinger → «Ny signeringsnøkkel»",name:"portal-webhook-secret",autoComplete:"new-password","data-1p-ignore":!0,"data-lpignore":"true","data-form-type":"other",className:`${m} font-mono`})}),e.jsxs("label",{className:"flex items-center gap-2 text-xs text-[#8b7355]",children:[e.jsx("input",{type:"checkbox",checked:d,onChange:o=>n(o.target.checked)}),"Vis nøkler i klartekst"]}),e.jsx(x,{label:"Selskaps-ID (company_id, standard)",children:e.jsx("input",{value:t.default_company_id,onChange:o=>r({...t,default_company_id:o.target.value.trim()}),placeholder:"UUID fra Admin → Selskaper i portalen",className:`${m} font-mono`})}),e.jsx(x,{label:"Return-URL (kunden sendes hit etter betaling)",children:e.jsx("input",{value:t.return_url,onChange:o=>r({...t,return_url:o.target.value.trim()}),placeholder:`${k}/betaling/retur`,className:`${m} font-mono`})}),e.jsx(x,{label:"Webhook-URL (vår mottaker — oppgis i portalen)",children:e.jsx("input",{value:t.webhook_url||`${k}/api/public/portal-webhook`,onChange:o=>r({...t,webhook_url:o.target.value.trim()}),className:`${m} font-mono`})}),e.jsxs("p",{className:"text-xs text-[#8b7355]",children:["Vi verifiserer ",e.jsx("code",{className:"font-mono",children:"x-
1portal-signature: t=<unix>,v1=<hex>"})," ","(HMAC-SHA256 over ",e.jsx("code",{className:"font-mono",children:"<t>.<body>"}),"). Dokumentasjon:"," ",e.jsx("code",{className:"font-mono",children:"/api-docs"}),", ",e.jsx("code",{className:"font-mono",children:"/swagger"}),","," ",e.jsx("code",{className:"font-mono",children:"/api/public/v1/openapi.json"}),"."]}),e.jsx(x,{label:"Miljø",children:e.jsxs("select",{value:t.environment,onChange:o=>r({...t,environment:o.target.value}),className:m,children:[e.jsx("option",{value:"test",children:"Test / sandbox"}),e.jsx("option",{value:"production",children:"Produksjon"})]})}),e.jsx(x,{label:"Standard mva-kode",children:e.jsx("input",{value:t.default_vat_code,onChange:o=>r({...t,default_vat_code:o.target.value}),className:m})}),e.jsxs("label",{className:"flex items-center gap-2 text-sm text-[#6f5b41]",children:[e.jsx("input",{type:"checkbox",checked:t.enabled,onChange:o=>r({...t,enabled:o.target.checked})}),"Aktiver portalen (må stå av til vi har testet ferdig)"]}),e.jsx(x,{label:"Notater",children:e.jsx("textarea",{value:t.notes??"",onChange:o=>r({...t,notes:o.target.value}),rows:3,className:"w-full rounded-2xl border border-[#d8cdb8] bg-white px-3 py-2 text-sm"})}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("button",{onClick:()=>S("save",()=>c({data:t})),disabled:f!==null,className:"rounded-full bg-[#8b7355] px-5 py-2 text-sm text-white disabled:opacity-50",children:f==="save"?"Lagrer…":"Lagre"}),e.jsx("button",{onClick:()=>S("test",T),disabled:f!==null,className:"rounded-full bg-[#3d3225] px-4 py-2 text-sm text-white disabled:opacity-50",children:f==="test"?"Tester…":"Test tilkobling"}),e.jsx("button",{onClick:()=>S("import",()=>l()),disabled:f!==null,className:"rounded-full border border-[#d8cdb8] px-4 py-2 text-sm text-[#6f5b41] disabled:opacity-50",children:f==="import"?"Importerer…":"Importer alt fra dagens løsning"}),u&&e.jsx("span",{className:"text-xs text-[#6f5b41]",children:u})]})]})]})}function Q({data:s,onDone:i}){const c=g(E),h=g(D),l=g(I),[a,t]=p.useState(null);return e.jsxs(N,{title:"Firmaer / juridiske selskaper",children:[e.jsx("p",{className:"text-xs text-[#8b7355]",children:"Hvert produkt må knyttes til et firma i portalen (org.nr., Vipps MSN og bankkonto)."}),e.jsxs("div",{className:"space-y-4",children:[s.companies.map(r=>e.jsx(G,{c:r,owners:s.owners,onSave:async d=>{await c({data:{id:r.id,...d}}),i()},onDelete:async()=>{await h({data:{id:r.id}}),i()},onPush:async()=>{t(null);try{await l({data:{kind:"company",id:r.id}}),t("Sendt til portalen ✓"),i()}catch(d){t(`Feil: ${d?.message??d}`)}}},r.id)),s.companies.length===0&&e.jsx("p",{className:"text-sm text-[#8b7355]",children:"Ingen firmaer ennå — kjør «Importer alt fra dagens løsning» under Innstillinger."}),a&&e.jsx("p",{className:"text-xs text-[#6f5b41]",children:a})]})]})}function G({c:s,owners:i,onSave:c,onDelete:h,onPush:l}){const[a,t]=p.useState({name:s.name??"",org_number:s.org_number??"",vipps_msn:s.vipps_msn??"",bank_account:s.bank_account??"",default_vat_code:s.default_vat_code??"25",portal_company_id:s.portal_company_id??"",owner_id:s.owner_id??""}),[r,d]=p.useState(!1);return e.jsxs("div",{className:"rounded-2xl border border-[#e6dfd1] p-4",children:[e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2 lg:grid-cols-3",children:[e.jsx(x,{label:"Navn",children:e.jsx("input",{value:a.name,onChange:n=>t({...a,name:n.target.value}),className:m})}),e.jsx(x,{label:"Org.nr",children:e.jsx("input",{value:a.org_number,onChange:n=>t({...a,org_number:n.target.value}),className:m})}),e.jsx(x,{label:"Vipps MSN",children:e.jsx("input",{value:a.vipps_msn,onChange:n=>t({...a,vipps_msn:n.target.value}),className:m})}),e.jsx(x,{label:"Bankkonto",children:e.jsx("input",{value:a.bank_account,onChange:n=>t({...a,bank_account:n.target.value}),className:m})}),e.jsx(x,{label:"Standard mva-kode",children:e.jsx("input",{value:a.default_vat_code,onChange:n=>t({...a,default_vat_code:n.target.value}),className:m})}),e.jsx(x,{label:"Portalens firma-ID",children:e.jsx("input",{value:a.portal_company_id,onChange:n=>t({...a,portal_company_id:n.target.value}),placeholder:"fylles ved synk",className:`${m} font-mono`})}),e.jsx(x,{label:"Vår eier",children:e.jsxs("select",{value:a.owner_id??"",onChange:n=>t({...a,owner_id:n.target.value}),className:m,children:[e.jsx("option",{value:"",children:"— ingen —"}),i.map(n=>e.jsx("option",{value:n.id,children:n.name},n.id))]})})]}),e.jsxs("div",{className:"mt-3 flex flex-wrap items-center gap-3",children:[e.jsx("button",{disabled:r,onClick:async()=>{d(!0),await c({...a,owner_id:a.owner_id||null}),d(!1)},className:"rounded-full bg-[#8b7355] px-4 py-1.5 text-xs text-white disabled:opacity-50",children:"Lagre"}),e.jsx("button",{disabled:r,onClick:l,className:"rounded-full bg-[#3d3225] px-4 py-1.5 text-xs text-white disabled:opacity-50",children:"Send til portal"}),e.jsx("button",{disabled:r,onClick:h,className:"rounded-full border border-[#d8cdb8] px-4 py-1.5 text-xs text-[#8b7355]",children:"Slett"}),e.jsxs("span",{className:"text-xs text-[#8b7355]",children:["Status: ",s.sync_status,s.sync_error?` — ${s.sync_error}`:""]})]})]})}function J({data:s,onDone:i}){const c=g(B),h=g(I),[l,a]=p.useState("event"),[t,r]=p.useState(""),[d,n]=p.useState(null),k=p.useMemo(()=>s.products.filter(u=>u.source_type===l&&(t.trim()===""||`${u.name} ${u.sku??""}`.toLowerCase().includes(t.trim().toLowerCase()))),[s.products,l,t]);return e.jsxs(N,{title:"Produkter & arrangementer",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[Object.entries(U).map(([u,b])=>{const f=s.products.filter(w=>w.source_type===u).length;return e.jsxs("button",{onClick:()=>a(u),className:`rounded-full px-3 py-1 text-xs ${l===u?"bg-[#3d3225] text-white":"bg-[#f7f3eb] text-[#6f5b41]"}`,children:[b," (",f,")"]},u)}),e.jsx("input",{value:t,onChange:u=>r(u.target.value),placeholder:"Søk…",className:"ml-auto w-48 rounded-full border border-[#d8cdb8] bg-white px-3 py-1 text-sm"})]}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full min-w-[840px] text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"text-left text-xs uppercase tracking-wide text-[#8b7355]",children:[e.jsx("th",{className:"py-2",children:"Med"}),e.jsx("th",{children:"Navn"}),e.jsx("th",{children:"Artikkelnr"}),e.jsx("th",{children:"Pris (kr)"}),e.jsx("th",{children:"Mva"}),e.jsx("th",{children:"Firma"}),e.jsx("th",{children:"Portal-ID"}),e.jsx("th",{})]})}),e.jsx("tbody",{children:k.map(u=>e.jsx(W,{p:u,companies:s.companies,onSave:async b=>{await c({data:{id:u.id,...b}}),i()},onPush:async()=>{n(null);try{await h({data:{kind:"product",id:u.id}}),n("Sendt til portalen ✓"),i()}
1catch(b){n(`Feil: ${b?.message??b}`)}}},u.id))})]})}),k.length===0&&e.jsx("p",{className:"text-sm text-[#8b7355]",children:"Ingen linjer — kjør «Importer alt fra dagens løsning» under Innstillinger."}),d&&e.jsx("p",{className:"text-xs text-[#6f5b41]",children:d})]})}function W({p:s,companies:i,onSave:c,onPush:h}){const[l,a]=p.useState({include_in_portal:s.include_in_portal,name:s.name??"",sku:s.sku??"",price:String((s.price_ore??0)/100),vat_code:s.vat_code??"25",company_id:s.company_id??""}),[t,r]=p.useState(!1),d="rounded-full border border-[#d8cdb8] bg-white px-2 py-1 text-sm";return e.jsxs("tr",{className:"border-t border-[#efe8db] align-middle",children:[e.jsx("td",{className:"py-2",children:e.jsx("input",{type:"checkbox",checked:l.include_in_portal,onChange:n=>a({...l,include_in_portal:n.target.checked})})}),e.jsx("td",{className:"pr-2",children:e.jsx("input",{value:l.name,onChange:n=>a({...l,name:n.target.value}),className:`${d} w-56`})}),e.jsx("td",{className:"pr-2",children:e.jsx("input",{value:l.sku,onChange:n=>a({...l,sku:n.target.value}),className:`${d} w-28 font-mono`})}),e.jsx("td",{className:"pr-2",children:e.jsx("input",{value:l.price,onChange:n=>a({...l,price:n.target.value}),inputMode:"decimal",className:`${d} w-24`})}),e.jsx("td",{className:"pr-2",children:e.jsx("input",{value:l.vat_code,onChange:n=>a({...l,vat_code:n.target.value}),className:`${d} w-16`})}),e.jsx("td",{className:"pr-2",children:e.jsxs("select",{value:l.company_id??"",onChange:n=>a({...l,company_id:n.target.value}),className:`${d} w-40`,children:[e.jsx("option",{value:"",children:"—"}),i.map(n=>e.jsx("option",{value:n.id,children:n.name},n.id))]})}),e.jsx("td",{className:"pr-2 font-mono text-xs text-[#8b7355]",children:s.portal_product_id??"—"}),e.jsxs("td",{className:"whitespace-nowrap",children:[e.jsx("button",{disabled:t,onClick:async()=>{r(!0),await c({include_in_portal:l.include_in_portal,name:l.name,sku:l.sku||null,price_ore:Math.round(Number(l.price.replace(",",".")||0)*100),vat_code:l.vat_code,company_id:l.company_id||null}),r(!1)},className:"rounded-full bg-[#8b7355] px-3 py-1 text-xs text-white disabled:opacity-50",children:"Lagre"}),e.jsx("button",{disabled:t,onClick:h,className:"ml-2 rounded-full bg-[#3d3225] px-3 py-1 text-xs text-white disabled:opacity-50",children:"Send"})]})]})}function Y({data:s}){return e.jsx(N,{title:"Synk-logg",children:e.jsxs("ul",{className:"space-y-2 text-sm",children:[s.log.map(i=>e.jsxs("li",{className:"flex gap-3 border-b border-[#efe8db] pb-2",children:[e.jsx("span",{className:i.ok?"text-[#2f6b46]":"text-[#a33]",children:i.ok?"OK":"FEIL"}),e.jsx("span",{className:"text-xs text-[#8b7355]",children:new Date(i.created_at).toLocaleString("nb-NO")}),e.jsx("span",{className:"font-mono text-xs",children:i.kind}),e.jsx("span",{className:"text-xs text-[#6f5b41]",children:i.message})]},i.id)),s.log.length===0&&e.jsx("li",{className:"text-[#8b7355]",children:"Ingen hendelser ennå."})]})})}export{ee as component};

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.