diff --git a/.github/workflows/build_panel_assets.yml b/.github/workflows/build_panel_assets.yml index 6255b5307e..fd37dee055 100644 --- a/.github/workflows/build_panel_assets.yml +++ b/.github/workflows/build_panel_assets.yml @@ -19,6 +19,9 @@ on: - "packages/panel/resources/**" - "packages/panel/vite.config.ts" - "packages/panel/package.json" + - "packages/bundles/resources/js/**" + - "packages/bundles/vite.config.js" + - "packages/bundles/package.json" - ".github/workflows/build_panel_assets.yml" permissions: @@ -58,8 +61,11 @@ jobs: run: npx vite build working-directory: packages/panel + - name: Build bundles add-on bundle + run: npm run build --workspace @lunarphp/bundles-addon + - name: Commit built assets uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: "chore(panel): rebuild compiled assets" - file_pattern: packages/panel/public/build + file_pattern: packages/panel/public/build packages/bundles/build diff --git a/.github/workflows/split_packages.yml b/.github/workflows/split_packages.yml index fdc8592a84..63b0cb2d50 100644 --- a/.github/workflows/split_packages.yml +++ b/.github/workflows/split_packages.yml @@ -12,6 +12,7 @@ jobs: matrix: package: - "admin" + - "bundles" - "core" - "demo-data" - "filament" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0f19566bd7..cbb7c43443 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -24,7 +24,7 @@ jobs: php: ${{ fromJSON(github.event_name == 'pull_request' && '["8.4"]' || '["8.4","8.5"]') }} laravel: ["12.*", "13.*"] dependency-version: [prefer-stable] - testsuite: [core, admin, panel, filament, shipping, stripe, paypal, search, upgrade] + testsuite: [core, admin, panel, filament, shipping, stripe, paypal, search, bundles, upgrade] include: - laravel: 12.* testbench: 10.* @@ -196,6 +196,9 @@ jobs: - name: Build example add-on bundle run: npm run build --workspace @lunarphp/panel-addon-example + - name: Build bundles add-on bundle + run: npm run build --workspace @lunarphp/bundles-addon + # Fails when a publishable npm package's content no longer matches the # tarball published under its current version — the reminder to bump. # Relies on the panel build above for fresh @lunarphp/panel types. diff --git a/TODO.md b/TODO.md index 8a81b47be2..5d45d80d8f 100644 --- a/TODO.md +++ b/TODO.md @@ -34,6 +34,7 @@ Items tagged _(judgement)_ are genuine line-calls worth revisiting. ## Done +- Product bundles — `lunarphp/bundles`: a variant with components, derived stock, component order lines, panel editor (spec 0085) - Attribute field-type configuration schema — field types declare their settings once in core; the panel and Filament bridge both render from the descriptors (spec 0054) - Filament admin & bridge hardening — standalone bridge, dead hooks and config, locale nav groups, guard and asset id (spec 0076) - First staff account creation in core — `lunar:create-admin` moves out of the Filament admin; panel install offers it (spec 0075) diff --git a/composer.json b/composer.json index 891af14e05..3670b9dd1f 100644 --- a/composer.json +++ b/composer.json @@ -62,6 +62,8 @@ "psr-4": { "Lunar\\Core\\": "packages/core/src", "Lunar\\Admin\\": "packages/admin/src/", + "Lunar\\Bundles\\": "packages/bundles/src/", + "Lunar\\Bundles\\Database\\Factories\\": "packages/bundles/database/factories", "Lunar\\Core\\Database\\Factories\\": "packages/core/database/factories", "Lunar\\Core\\Database\\Seeders\\": "packages/core/database/seeders", "Lunar\\Core\\Database\\State\\": "packages/core/database/state", @@ -85,6 +87,7 @@ "psr-4": { "Lunar\\Tests\\": "tests", "Lunar\\Tests\\Admin\\": "tests/admin", + "Lunar\\Tests\\Bundles\\": "tests/bundles", "Lunar\\Tests\\Core\\": "tests/core", "Lunar\\Tests\\DemoData\\": "tests/demo-data", "Lunar\\Tests\\Filament\\": "tests/filament", @@ -103,6 +106,7 @@ "name": [ "Table Rate Shipping", "Search", + "Bundles", "Meilisearch", "Paypal Payments", "Stripe Payments", @@ -119,6 +123,7 @@ "Lunar\\Filament\\LunarFilamentServiceProvider", "Lunar\\Admin\\LunarPanelProvider", "Lunar\\Shipping\\ShippingServiceProvider", + "Lunar\\Bundles\\BundlesServiceProvider", "Lunar\\Upgrade\\UpgradeServiceProvider", "Lunar\\DemoData\\DemoDataServiceProvider", "Lunar\\Panel\\PanelServiceProvider", @@ -129,6 +134,7 @@ "replace": { "lunarphp/core": "self.version", "lunarphp/admin": "self.version", + "lunarphp/bundles": "self.version", "lunarphp/demo-data": "self.version", "lunarphp/filament": "self.version", "lunarphp/meilisearch": "self.version", diff --git a/package.json b/package.json index 4fe6256e60..45c9ebb571 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "workspaces": [ "packages/panel/resources/package", "packages/panel/resources/panel-package", - "packages/panel-addon-example" + "packages/panel-addon-example", + "packages/bundles" ], "scripts": { "check-npm-drift": "node scripts/check-npm-drift.mjs" diff --git a/packages/bundles/.github/workflows/close-pull-request.yml b/packages/bundles/.github/workflows/close-pull-request.yml new file mode 100644 index 0000000000..20d45a5f61 --- /dev/null +++ b/packages/bundles/.github/workflows/close-pull-request.yml @@ -0,0 +1,13 @@ +name: Close Pull Request + +on: + pull_request_target: + types: [opened] + +jobs: + run: + runs-on: ubuntu-latest + steps: + - uses: superbrothers/close-pull-request@v3 + with: + comment: "Thank you for your pull request. However, you have submitted this PR on the Lunar Bundles Repo which is a read-only sub split of `lunarphp/lunar`. Please submit your PR on the https://github.com/lunarphp/lunar repository.

Thanks!" diff --git a/packages/bundles/.gitignore b/packages/bundles/.gitignore new file mode 100644 index 0000000000..c2658d7d1b --- /dev/null +++ b/packages/bundles/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/packages/bundles/README.md b/packages/bundles/README.md new file mode 100644 index 0000000000..e9326a6d36 --- /dev/null +++ b/packages/bundles/README.md @@ -0,0 +1,16 @@ +# Lunar Bundles + +Sell a set of product variants as one product. A bundle is an ordinary `ProductVariant` that carries a component list: stock is derived from the components, the price is either fixed or derived from the components, and the order records one component line per part so fulfilment and stock commitment work unchanged. + +```php +$bundle = app(DefinesBundle::class)->execute($variant, BundlePricing::Components, discountPercentage: 10); + +$bundle->syncComponents([ + ['variant' => $body, 'quantity' => 1], + ['variant' => $bag, 'quantity' => 1], +]); + +CartSession::add($variant, 1); +``` + +See spec `0085-product-bundles` in the monorepo for the full design. diff --git a/packages/bundles/build/assets/addon-Bd9bHYW_.js b/packages/bundles/build/assets/addon-Bd9bHYW_.js new file mode 100644 index 0000000000..74d8d29274 --- /dev/null +++ b/packages/bundles/build/assets/addon-Bd9bHYW_.js @@ -0,0 +1 @@ +(function(e,D,B,i){"use strict";const I=a=>{var p;return((p=a.panel)==null?void 0:p.path)??"panel"},R={class:"flex items-center gap-2.5 min-w-0"},j={class:"w-8 h-8 shrink-0 rounded-md border border-line bg-surface-2 overflow-hidden flex items-center justify-center text-ink-400"},O=["src"],A={class:"min-w-0"},Q={class:"text-[12.5px] font-medium text-ink-900 truncate"},H={class:"text-[11px] text-ink-500 truncate"},J={key:0,class:"font-mono"},K={key:1},W={key:2},q=e.defineComponent({__name:"VariantThumb",props:{variant:{}},setup(a){return(p,o)=>(e.openBlock(),e.createElementBlock("div",R,[e.createElementVNode("div",j,[a.variant.thumbnail?(e.openBlock(),e.createElementBlock("img",{key:0,src:a.variant.thumbnail,alt:"",class:"w-full h-full object-cover"},null,8,O)):(e.openBlock(),e.createBlock(e.unref(i.Icon),{key:1,name:"image",cls:"sm"}))]),e.createElementVNode("div",A,[e.createElementVNode("div",Q,e.toDisplayString(a.variant.name),1),e.createElementVNode("div",H,[a.variant.sku?(e.openBlock(),e.createElementBlock("span",J,e.toDisplayString(a.variant.sku),1)):e.createCommentVNode("",!0),a.variant.sku&&a.variant.option?(e.openBlock(),e.createElementBlock("span",K," / ")):e.createCommentVNode("",!0),a.variant.option?(e.openBlock(),e.createElementBlock("span",W,e.toDisplayString(a.variant.option),1)):e.createCommentVNode("",!0)])])]))}}),X={key:0,class:"px-3 py-3 text-[12px] text-ink-500"},Y={key:1,class:"divide-y divide-line"},Z={key:0,class:"flex items-center gap-1.5 text-[11px] text-ink-500 shrink-0"},v={class:"w-[84px] shrink-0"},ee={class:"flex items-center gap-0.5 shrink-0"},F=e.defineComponent({__name:"ComponentList",props:{components:{},withDefault:{type:Boolean},disabled:{type:Boolean},emptyText:{}},emits:["quantity","move","remove","default"],setup(a,{emit:p}){const o=p,{t:s}=B.useI18n(),d=(r,g)=>{const m=Math.max(1,Math.floor(Number(g.target.value))||1);m!==r.quantity&&o("quantity",r,m)};return(r,g)=>a.components.length?(e.openBlock(),e.createElementBlock("ul",Y,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(a.components,(m,f)=>(e.openBlock(),e.createElementBlock("li",{key:m.id,class:"flex items-center gap-3 px-3 py-2"},[e.createVNode(q,{variant:m.variant,class:"flex-1"},null,8,["variant"]),a.withDefault?(e.openBlock(),e.createElementBlock("label",Z,[e.createVNode(e.unref(i.Checkbox),{"model-value":m.default,"aria-label":e.unref(s)("bundles::bundles.panel.group_default"),"onUpdate:modelValue":x=>o("default",m,x)},null,8,["model-value","aria-label","onUpdate:modelValue"]),e.createTextVNode(" "+e.toDisplayString(e.unref(s)("bundles::bundles.panel.group_default")),1)])):e.createCommentVNode("",!0),e.createElementVNode("div",v,[e.createVNode(e.unref(i.TextInput),{type:"number",min:"1",step:"1","model-value":m.quantity,disabled:a.disabled,"aria-label":e.unref(s)("bundles::bundles.panel.quantity"),onChange:x=>d(m,x)},{prefix:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(e.unref(s)("bundles::bundles.panel.quantity")),1)]),_:1},8,["model-value","disabled","aria-label","onChange"])]),e.createElementVNode("div",ee,[e.createVNode(e.unref(i.Button),{variant:"ghost",size:"sm",icon:"chevDown","icon-cls":"sm rotate-180",disabled:a.disabled||f===0,"aria-label":e.unref(s)("bundles::bundles.panel.move_up"),title:e.unref(s)("bundles::bundles.panel.move_up"),onClick:x=>o("move",m,-1)},null,8,["disabled","aria-label","title","onClick"]),e.createVNode(e.unref(i.Button),{variant:"ghost",size:"sm",icon:"chevDown",disabled:a.disabled||f===a.components.length-1,"aria-label":e.unref(s)("bundles::bundles.panel.move_down"),title:e.unref(s)("bundles::bundles.panel.move_down"),onClick:x=>o("move",m,1)},null,8,["disabled","aria-label","title","onClick"]),e.createVNode(e.unref(i.Button),{variant:"ghost",size:"sm",icon:"trash",disabled:a.disabled,"aria-label":e.unref(s)("bundles::bundles.panel.remove"),title:e.unref(s)("bundles::bundles.panel.remove"),onClick:x=>o("remove",m)},null,8,["disabled","aria-label","title","onClick"])])]))),128))])):(e.openBlock(),e.createElementBlock("div",X,e.toDisplayString(a.emptyText),1))}}),te={class:"flex flex-col gap-3"},ne={class:"flex flex-wrap items-end gap-3 px-3 py-2.5 bg-surface-2 border-b border-line"},le={class:"flex-1 min-w-[180px]"},oe={class:"w-[72px]"},ae={class:"w-[72px]"},ie={class:"flex items-center gap-0.5 pb-0.5"},se={class:"px-3 py-2 border-t border-line"},de=e.defineComponent({__name:"GroupsEditor",props:{groups:{},components:{},defaultLanguage:{},disabled:{type:Boolean}},emits:["add","update","move","remove","add-option","component-quantity","component-move","component-remove","component-default"],setup(a,{emit:p}){const o=a,s=p,{t:d}=B.useI18n(),r=_=>o.components.filter(u=>u.group_id===_.id),g=_=>_.name[o.defaultLanguage]??_.label??"",m=(_,u)=>{const c=u.target.value.trim();c&&c!==g(_)&&s("update",_,{name:{..._.name,[o.defaultLanguage]:c}})},f=(_,u,c)=>{const y=Math.max(u==="min_selections"?0:1,Math.floor(Number(c.target.value))||0);y!==_[u]&&s("update",_,{[u]:y})},x=e.ref(null);return(_,u)=>(e.openBlock(),e.createElementBlock("div",te,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(a.groups,(c,y)=>(e.openBlock(),e.createElementBlock("div",{key:c.id,class:"border border-line rounded-lg bg-surface overflow-hidden"},[e.createElementVNode("div",ne,[e.createElementVNode("div",le,[e.createVNode(e.unref(i.FieldLabel),{for:`bundle-group-${c.id}-name`,hint:a.defaultLanguage.toUpperCase()},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(e.unref(d)("bundles::bundles.panel.group_name")),1)]),_:1},8,["for","hint"]),e.createVNode(e.unref(i.TextInput),{id:`bundle-group-${c.id}-name`,"model-value":g(c),disabled:a.disabled,onChange:b=>m(c,b)},null,8,["id","model-value","disabled","onChange"])]),e.createElementVNode("div",oe,[e.createVNode(e.unref(i.FieldLabel),{for:`bundle-group-${c.id}-min`},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(e.unref(d)("bundles::bundles.panel.group_min")),1)]),_:1},8,["for"]),e.createVNode(e.unref(i.TextInput),{id:`bundle-group-${c.id}-min`,type:"number",min:"0",step:"1","model-value":c.min_selections,disabled:a.disabled,onChange:b=>f(c,"min_selections",b)},null,8,["id","model-value","disabled","onChange"])]),e.createElementVNode("div",ae,[e.createVNode(e.unref(i.FieldLabel),{for:`bundle-group-${c.id}-max`},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(e.unref(d)("bundles::bundles.panel.group_max")),1)]),_:1},8,["for"]),e.createVNode(e.unref(i.TextInput),{id:`bundle-group-${c.id}-max`,type:"number",min:"1",step:"1","model-value":c.max_selections,disabled:a.disabled,onChange:b=>f(c,"max_selections",b)},null,8,["id","model-value","disabled","onChange"])]),e.createElementVNode("div",ie,[e.createVNode(e.unref(i.Button),{variant:"ghost",size:"sm",icon:"chevDown","icon-cls":"sm rotate-180",disabled:a.disabled||y===0,"aria-label":e.unref(d)("bundles::bundles.panel.move_up"),title:e.unref(d)("bundles::bundles.panel.move_up"),onClick:b=>s("move",c,-1)},null,8,["disabled","aria-label","title","onClick"]),e.createVNode(e.unref(i.Button),{variant:"ghost",size:"sm",icon:"chevDown",disabled:a.disabled||y===a.groups.length-1,"aria-label":e.unref(d)("bundles::bundles.panel.move_down"),title:e.unref(d)("bundles::bundles.panel.move_down"),onClick:b=>s("move",c,1)},null,8,["disabled","aria-label","title","onClick"]),e.createVNode(e.unref(i.Button),{variant:"ghost",size:"sm",icon:"trash",disabled:a.disabled,"aria-label":e.unref(d)("bundles::bundles.panel.remove_group"),title:e.unref(d)("bundles::bundles.panel.remove_group"),onClick:b=>x.value=c},null,8,["disabled","aria-label","title","onClick"])])]),e.createVNode(F,{components:r(c),disabled:a.disabled,"empty-text":e.unref(d)("bundles::bundles.panel.group_empty"),"with-default":"",onQuantity:u[0]||(u[0]=(b,V)=>s("component-quantity",b,V)),onMove:u[1]||(u[1]=(b,V)=>s("component-move",b,V)),onRemove:u[2]||(u[2]=b=>s("component-remove",b)),onDefault:u[3]||(u[3]=(b,V)=>s("component-default",b,V))},null,8,["components","disabled","empty-text"]),e.createElementVNode("div",se,[e.createVNode(e.unref(i.Button),{size:"sm",icon:"plus",disabled:a.disabled,onClick:b=>s("add-option",c)},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(e.unref(d)("bundles::bundles.panel.add_option")),1)]),_:1},8,["disabled","onClick"])])]))),128)),e.createElementVNode("div",null,[e.createVNode(e.unref(i.Button),{icon:"plus",disabled:a.disabled,onClick:u[4]||(u[4]=c=>s("add"))},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(e.unref(d)("bundles::bundles.panel.add_group")),1)]),_:1},8,["disabled"])]),e.createVNode(e.unref(i.ConfirmDialog),{open:x.value!==null,title:e.unref(d)("bundles::bundles.panel.remove_group"),description:e.unref(d)("bundles::bundles.panel.confirm_remove_group"),tone:"danger","onUpdate:open":u[5]||(u[5]=c=>{c||(x.value=null)}),onConfirm:u[6]||(u[6]=()=>{x.value&&s("remove",x.value)})},null,8,["open","title","description"])]))}}),re={class:"flex flex-col gap-5"},ce={class:"flex items-center justify-between gap-4"},me={class:"flex items-center gap-2.5 text-[13px] text-ink-900 cursor-pointer"},pe={key:0,class:"text-[12px] text-ink-500","data-testid":"bundle-availability"},ue={key:0,class:"rounded-md border border-danger-border bg-danger-soft px-3 py-2 text-[12px] text-danger"},fe={class:"grid gap-3 sm:grid-cols-2"},be={value:"fixed"},ge={value:"components"},_e={key:0},ke={key:0,class:"text-[12px] text-ink-500 leading-normal"},xe={class:"flex items-center justify-between gap-3 mb-2"},ye={class:"text-[12.5px] font-semibold text-ink-900"},he={class:"text-[11.5px] text-ink-500"},Be={class:"border border-line rounded-lg bg-surface overflow-hidden"},Ve={key:1},Ne={class:"text-[12.5px] font-semibold text-ink-900 mb-2"},Ce={class:"w-full text-[12.5px] border border-line rounded-lg overflow-hidden"},Ee={class:"divide-y divide-line"},$e={class:"px-3 py-1.5 font-mono text-ink-700 w-[80px]"},De={key:0,class:"px-3 py-1.5 text-warn-ink"},we={key:1,class:"px-3 py-1.5 text-ink-900 [font-variant-numeric:tabular-nums]"},Se={key:0,class:"ml-2 text-ink-500 line-through"},Te={class:"mb-2"},Le={class:"text-[12.5px] font-semibold text-ink-900"},Ie={class:"text-[11.5px] text-ink-500"},qe=e.defineComponent({__name:"BundleEditor",props:{summary:{}},setup(a){const p=a,{t:o}=B.useI18n(),s=i.useToasts(),d=e.ref(p.summary);e.watch(()=>p.summary,n=>{d.value=n});const r=e.computed(()=>d.value.bundle),g=e.ref(!1),m=e.ref([]),f=async(n,l=o("bundles::bundles.panel.saved"))=>{g.value=!0,m.value=[];try{d.value=await n(),s.success(l)}catch(t){t instanceof i.ValidationError?m.value=Object.values(t.errors).flat():s.error(o("bundles::bundles.panel.load_failed"))}finally{g.value=!1}},x=e.ref(!1),_=(n,l)=>i.http.put(d.value.urls.define,{pricing:n,discount_percentage:l}),u=()=>{if(d.value.defined){x.value=!0;return}f(()=>_("fixed",null))},c=()=>{f(()=>i.http.delete(d.value.urls.destroy),o("bundles::bundles.panel.removed"))},y=e.ref(!1),b=n=>{if(!(!r.value||n===r.value.pricing)){if(n==="components"){y.value=!0;return}f(()=>_("fixed",null))}},V=()=>{f(()=>{var n;return _("components",((n=r.value)==null?void 0:n.discount_percentage)??null)})},We=n=>{const l=n.target.value.trim(),t=l===""?null:Number(l);r.value&&t!==r.value.discount_percentage&&f(()=>_(r.value.pricing,t))},M=n=>{var l;return(((l=r.value)==null?void 0:l.components)??[]).filter(t=>t.group_id===n)},Xe=e.computed(()=>M(null)),Ye=n=>{const l=new Map;return n.map(t=>{const k=l.get(t.group_id)??0;return l.set(t.group_id,k+1),{variant_id:t.variant.id,quantity:t.quantity,group_id:t.group_id,default:t.default,position:k}})},N=n=>{f(()=>i.http.put(d.value.urls.components,{components:Ye(n)}))},C=()=>{var n;return[...((n=r.value)==null?void 0:n.components)??[]]},P=(n,l)=>{N(C().map(t=>t.id===n.id?{...t,quantity:l}:t))},Ze=(n,l)=>{N(C().map(t=>t.id===n.id?{...t,default:l}:t))},U=n=>{N(C().filter(l=>l.id!==n.id))},z=(n,l)=>{const t=M(n.group_id),k=t.findIndex(L=>L.id===n.id),h=t[k+l];if(!h)return;const $=[...t];$[k]=h,$[k+l]=n,N([...C().filter(L=>L.group_id!==n.group_id),...$])},S=e.ref(!1),T=e.ref(null),G=n=>{T.value=n,S.value=!0},ve=n=>{const l=C(),t=n.filter(k=>!l.some(h=>h.group_id===T.value&&h.variant.id===k.id)).map((k,h)=>({id:-(h+1),public_id:"",group_id:T.value,quantity:1,default:!1,position:0,variant:{...k,id:k.id}}));t.length&&N([...l,...t])},et=n=>n.map((l,t)=>({id:l.id>0?l.id:null,name:l.name,min_selections:l.min_selections,max_selections:l.max_selections,position:t})),w=n=>{f(()=>i.http.put(d.value.urls.groups,{groups:et(n)}))},E=()=>{var n;return[...((n=r.value)==null?void 0:n.groups)??[]]},tt=()=>{w([...E(),{id:0,public_id:"",name:{[d.value.default_language]:o("bundles::bundles.panel.new_group_name")},label:"",min_selections:1,max_selections:1,position:E().length}])},nt=(n,l)=>{w(E().map(t=>t.id===n.id?{...t,...l}:t))},lt=n=>{w(E().filter(l=>l.id!==n.id))},ot=(n,l)=>{const t=E(),k=t.findIndex($=>$.id===n.id),h=t[k+l];h&&(t[k]=h,t[k+l]=n,w(t))},at=e.computed(()=>{var l;const n=(l=r.value)==null?void 0:l.availability;return n?n.unlimited?o("bundles::bundles.panel.availability_unlimited"):n.available>0?o("bundles::bundles.panel.availability_count",{count:n.available}):o("bundles::bundles.panel.availability_none"):""});return(n,l)=>(e.openBlock(),e.createElementBlock("div",re,[e.createElementVNode("div",ce,[e.createElementVNode("label",me,[e.createVNode(e.unref(i.Toggle),{on:d.value.defined,disabled:g.value,onToggle:u},null,8,["on","disabled"]),e.createTextVNode(" "+e.toDisplayString(e.unref(o)("bundles::bundles.panel.sell_as_bundle")),1)]),r.value?(e.openBlock(),e.createElementBlock("span",pe,e.toDisplayString(at.value),1)):e.createCommentVNode("",!0)]),m.value.length?(e.openBlock(),e.createElementBlock("div",ue,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(m.value,(t,k)=>(e.openBlock(),e.createElementBlock("div",{key:k},e.toDisplayString(t),1))),128))])):e.createCommentVNode("",!0),r.value?(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createElementVNode("div",fe,[e.createElementVNode("div",null,[e.createVNode(e.unref(i.FieldLabel),{for:"bundle-pricing"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(e.unref(o)("bundles::bundles.panel.pricing")),1)]),_:1}),(e.openBlock(),e.createBlock(e.unref(i.Select),{id:"bundle-pricing",key:r.value.pricing+String(y.value),"model-value":r.value.pricing,"onUpdate:modelValue":b},{default:e.withCtx(()=>[e.createElementVNode("option",be,e.toDisplayString(e.unref(o)("bundles::bundles.panel.pricing_fixed")),1),e.createElementVNode("option",ge,e.toDisplayString(e.unref(o)("bundles::bundles.panel.pricing_components")),1)]),_:1},8,["model-value"]))]),r.value.pricing==="components"?(e.openBlock(),e.createElementBlock("div",_e,[e.createVNode(e.unref(i.FieldLabel),{for:"bundle-discount",hint:e.unref(o)("bundles::bundles.panel.discount_hint")},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(e.unref(o)("bundles::bundles.panel.discount_percentage")),1)]),_:1},8,["hint"]),e.createVNode(e.unref(i.TextInput),{id:"bundle-discount",type:"number",min:"0",max:"100",step:"0.01","model-value":r.value.discount_percentage??"",disabled:g.value,onChange:We},{suffix:e.withCtx(()=>[...l[5]||(l[5]=[e.createTextVNode("%",-1)])]),_:1},8,["model-value","disabled"])])):e.createCommentVNode("",!0)]),r.value.pricing==="components"?(e.openBlock(),e.createElementBlock("p",ke,e.toDisplayString(e.unref(o)("bundles::bundles.panel.derived_note")),1)):e.createCommentVNode("",!0),e.createElementVNode("div",null,[e.createElementVNode("div",xe,[e.createElementVNode("div",null,[e.createElementVNode("div",ye,e.toDisplayString(e.unref(o)("bundles::bundles.panel.components")),1),e.createElementVNode("div",he,e.toDisplayString(e.unref(o)("bundles::bundles.panel.components_description")),1)]),e.createVNode(e.unref(i.Button),{size:"sm",icon:"plus",disabled:g.value,onClick:l[0]||(l[0]=t=>G(null))},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(e.unref(o)("bundles::bundles.panel.add_component")),1)]),_:1},8,["disabled"])]),e.createElementVNode("div",Be,[e.createVNode(F,{components:Xe.value,disabled:g.value,"empty-text":e.unref(o)("bundles::bundles.panel.components_empty"),onQuantity:P,onMove:z,onRemove:U},null,8,["components","disabled","empty-text"])])]),r.value.pricing==="components"&&r.value.prices.length?(e.openBlock(),e.createElementBlock("div",Ve,[e.createElementVNode("div",Ne,e.toDisplayString(e.unref(o)("bundles::bundles.panel.derived_prices")),1),e.createElementVNode("table",Ce,[e.createElementVNode("tbody",Ee,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(r.value.prices,t=>(e.openBlock(),e.createElementBlock("tr",{key:t.currency},[e.createElementVNode("td",$e,e.toDisplayString(t.currency),1),t.missing.length?(e.openBlock(),e.createElementBlock("td",De,e.toDisplayString(e.unref(o)("bundles::bundles.panel.missing_price",{components:t.missing.join(", ")})),1)):(e.openBlock(),e.createElementBlock("td",we,[e.createTextVNode(e.toDisplayString(t.price)+" ",1),t.list_price?(e.openBlock(),e.createElementBlock("span",Se,e.toDisplayString(t.list_price),1)):e.createCommentVNode("",!0)]))]))),128))])])])):e.createCommentVNode("",!0),e.createElementVNode("div",null,[e.createElementVNode("div",Te,[e.createElementVNode("div",Le,e.toDisplayString(e.unref(o)("bundles::bundles.panel.groups")),1),e.createElementVNode("div",Ie,e.toDisplayString(e.unref(o)("bundles::bundles.panel.groups_description")),1)]),e.createVNode(de,{groups:r.value.groups,components:r.value.components,"default-language":d.value.default_language,disabled:g.value,onAdd:tt,onUpdate:nt,onMove:ot,onRemove:lt,onAddOption:l[1]||(l[1]=t=>G(t.id)),onComponentQuantity:P,onComponentMove:z,onComponentRemove:U,onComponentDefault:Ze},null,8,["groups","components","default-language","disabled"])])],64)):e.createCommentVNode("",!0),e.createVNode(e.unref(i.ConfirmDialog),{open:y.value,"onUpdate:open":l[2]||(l[2]=t=>y.value=t),title:e.unref(o)("bundles::bundles.panel.confirm_components_title"),description:e.unref(o)("bundles::bundles.panel.confirm_components"),onConfirm:V},null,8,["open","title","description"]),e.createVNode(e.unref(i.ConfirmDialog),{open:x.value,"onUpdate:open":l[3]||(l[3]=t=>x.value=t),title:e.unref(o)("bundles::bundles.panel.confirm_remove_title"),description:e.unref(o)("bundles::bundles.panel.confirm_remove"),tone:"danger",onConfirm:c},null,8,["open","title","description"]),e.createVNode(e.unref(i.TargetPickerDialog),{open:S.value,"onUpdate:open":l[4]||(l[4]=t=>S.value=t),"search-url":d.value.urls.search,bucket:"components",kinds:["variants"],onAdd:ve},null,8,["open","search-url"])]))}}),Fe={class:"text-[12px] text-ink-500 mb-3"},Me={class:"border border-line rounded-lg bg-surface overflow-hidden divide-y divide-line"},Pe={key:1,class:"text-[11.5px] text-ink-500"},Ue=e.defineComponent({__name:"VariantBundleList",props:{variants:{}},setup(a){const{t:p}=B.useI18n();return(o,s)=>(e.openBlock(),e.createElementBlock("div",null,[e.createElementVNode("p",Fe,e.toDisplayString(e.unref(p)("bundles::bundles.panel.variant_summary_description")),1),e.createElementVNode("ul",Me,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(a.variants,d=>(e.openBlock(),e.createElementBlock("li",{key:d.variant.id,class:"flex items-center gap-3 px-3 py-2"},[e.createVNode(q,{variant:d.variant,class:"flex-1"},null,8,["variant"]),d.bundle?(e.openBlock(),e.createBlock(e.unref(i.StatusBadge),{key:0,tone:"sage",size:"sm"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(e.unref(p)("bundles::bundles.panel.variant_component_count",d.bundle.components.length)),1)]),_:2},1024)):(e.openBlock(),e.createElementBlock("span",Pe,e.toDisplayString(e.unref(p)("bundles::bundles.panel.variant_not_bundle")),1)),e.createVNode(e.unref(D.Link),{href:d.variant.edit_url,class:"inline-flex items-center gap-1 text-[12px] text-ink-700 underline underline-offset-2 hover:text-ink-900"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(e.unref(p)("bundles::bundles.panel.edit_variant"))+" ",1),e.createVNode(e.unref(i.Icon),{name:"chevRight",cls:"sm"})]),_:1},8,["href"])]))),128))])]))}}),ze={key:0,class:"text-[12px] text-danger"},Ge=e.defineComponent({__name:"BundleCard",props:{product:{},variant:{}},setup(a){const p=a,{t:o}=B.useI18n(),s=e.ref(null),d=e.ref(!1),r=I(D.usePage().props);return e.onMounted(async()=>{try{if(p.variant)s.value=[await i.http.get(`/${r}/bundles/variants/${p.variant.id}`)];else if(p.product){const g=await i.http.get(`/${r}/bundles/products/${p.product.id}`);s.value=g.variants}}catch{d.value=!0}}),(g,m)=>s.value||d.value?(e.openBlock(),e.createBlock(e.unref(i.Section),{key:0,title:e.unref(o)("bundles::bundles.panel.card_title")},{desc:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(e.unref(o)("bundles::bundles.panel.card_description")),1)]),default:e.withCtx(()=>[d.value?(e.openBlock(),e.createElementBlock("p",ze,e.toDisplayString(e.unref(o)("bundles::bundles.panel.load_failed")),1)):s.value&&s.value.length===1?(e.openBlock(),e.createBlock(qe,{key:1,summary:s.value[0]},null,8,["summary"])):s.value?(e.openBlock(),e.createBlock(Ue,{key:2,variants:s.value},null,8,["variants"])):e.createCommentVNode("",!0)]),_:1},8,["title"])):e.createCommentVNode("",!0)}}),Re=e.defineComponent({__name:"BundleBadge",props:{row:{},value:{}},setup(a){const{t:p}=B.useI18n();return(o,s)=>a.value?(e.openBlock(),e.createBlock(e.unref(i.StatusBadge),{key:0,tone:"sage",size:"sm"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(e.unref(p)("bundles::bundles.panel.badge_bundle")),1)]),_:1})):e.createCommentVNode("",!0)}}),je={class:"flex flex-col gap-2.5"},Oe={key:0,class:"text-ink-500 font-normal"},Ae={class:"mt-0.5 text-[11.5px] text-ink-500"},Qe={key:0,class:"font-mono"},He={key:1},Je={class:"mt-3 text-[11px] text-ink-500"},Ke=e.defineComponent({__name:"IncludedInBundlesCard",props:{product:{}},setup(a){const p=a,{t:o}=B.useI18n(),s=e.ref([]),d=I(D.usePage().props);return e.onMounted(async()=>{if(p.product)try{const r=await i.http.get(`/${d}/bundles/products/${p.product.id}/included-in`);s.value=r.data}catch{s.value=[]}}),(r,g)=>s.value.length?(e.openBlock(),e.createBlock(e.unref(i.SideCard),{key:0,title:e.unref(o)("bundles::bundles.panel.included_in_title")},{default:e.withCtx(()=>[e.createElementVNode("ul",je,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(s.value,m=>(e.openBlock(),e.createElementBlock("li",{key:m.id},[e.createVNode(e.unref(D.Link),{href:m.product_url,class:"block text-[12.5px] font-medium text-ink-900 hover:underline underline-offset-2 truncate"},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(m.variant.name),1),m.variant.option?(e.openBlock(),e.createElementBlock("span",Oe," ("+e.toDisplayString(m.variant.option)+")",1)):e.createCommentVNode("",!0)]),_:2},1032,["href"]),e.createElementVNode("ul",Ae,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(m.components,f=>(e.openBlock(),e.createElementBlock("li",{key:f.variant.id,class:"truncate"},[e.createTextVNode(e.toDisplayString(e.unref(o)("bundles::bundles.panel.included_quantity",{quantity:f.quantity}))+" ",1),f.variant.sku?(e.openBlock(),e.createElementBlock("span",Qe,e.toDisplayString(f.variant.sku),1)):e.createCommentVNode("",!0),f.variant.option?(e.openBlock(),e.createElementBlock("span",He,e.toDisplayString(f.variant.option),1)):e.createCommentVNode("",!0)]))),128))])]))),128))]),e.createElementVNode("p",Je,e.toDisplayString(e.unref(o)("bundles::bundles.panel.included_in_description")),1)]),_:1},8,["title"])):e.createCommentVNode("",!0)}});window.LunarPanel.registerComponents("bundles",{BundleCard:Ge,BundleBadge:Re,IncludedInBundlesCard:Ke})})(Vue,InertiaVue3,VueI18n,LunarPanelUI); diff --git a/packages/bundles/build/manifest.json b/packages/bundles/build/manifest.json new file mode 100644 index 0000000000..ee4bf9d16a --- /dev/null +++ b/packages/bundles/build/manifest.json @@ -0,0 +1,8 @@ +{ + "resources/js/addon.ts": { + "file": "assets/addon-Bd9bHYW_.js", + "name": "addon", + "src": "resources/js/addon.ts", + "isEntry": true + } +} \ No newline at end of file diff --git a/packages/bundles/composer.json b/packages/bundles/composer.json new file mode 100644 index 0000000000..b3ad50fa85 --- /dev/null +++ b/packages/bundles/composer.json @@ -0,0 +1,48 @@ +{ + "name": "lunarphp/bundles", + "type": "library", + "description": "Product bundles for LunarPHP: sell a set of variants as one product with derived stock, component-derived pricing and component order lines.", + "keywords": [ + "lunarphp", + "laravel", + "ecommerce", + "e-commerce", + "headless", + "store", + "shop", + "bundles", + "kits" + ], + "license": "MIT", + "authors": [ + { + "name": "Lunar", + "homepage": "https://lunarphp.io/" + } + ], + "require": { + "php": "^8.4", + "lunarphp/core": "self.version" + }, + "suggest": { + "lunarphp/panel": "Adds the bundle editor to the product pages of the admin panel." + }, + "autoload": { + "psr-4": { + "Lunar\\Bundles\\": "src/", + "Lunar\\Bundles\\Database\\Factories\\": "database/factories" + } + }, + "extra": { + "lunar": { + "name": "Bundles" + }, + "laravel": { + "providers": [ + "Lunar\\Bundles\\BundlesServiceProvider" + ] + } + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/packages/bundles/config/bundles.php b/packages/bundles/config/bundles.php new file mode 100644 index 0000000000..156decf226 --- /dev/null +++ b/packages/bundles/config/bundles.php @@ -0,0 +1,13 @@ + 25, +]; diff --git a/packages/bundles/database/factories/BundleComponentFactory.php b/packages/bundles/database/factories/BundleComponentFactory.php new file mode 100644 index 0000000000..cae011f877 --- /dev/null +++ b/packages/bundles/database/factories/BundleComponentFactory.php @@ -0,0 +1,25 @@ + Bundle::factory(), + 'bundle_group_id' => null, + 'product_variant_id' => ProductVariant::factory(), + 'quantity' => 1, + 'default' => false, + 'position' => 0, + ]; + } +} diff --git a/packages/bundles/database/factories/BundleFactory.php b/packages/bundles/database/factories/BundleFactory.php new file mode 100644 index 0000000000..2a15e0aa3a --- /dev/null +++ b/packages/bundles/database/factories/BundleFactory.php @@ -0,0 +1,30 @@ + ProductVariant::factory(), + 'pricing' => BundlePricing::Fixed, + 'discount_percentage' => null, + ]; + } + + public function componentPriced(?float $discountPercentage = null): static + { + return $this->state([ + 'pricing' => BundlePricing::Components, + 'discount_percentage' => $discountPercentage, + ]); + } +} diff --git a/packages/bundles/database/factories/BundleGroupFactory.php b/packages/bundles/database/factories/BundleGroupFactory.php new file mode 100644 index 0000000000..240f5f3976 --- /dev/null +++ b/packages/bundles/database/factories/BundleGroupFactory.php @@ -0,0 +1,23 @@ + Bundle::factory(), + 'name' => ['en' => $this->faker->words(2, true)], + 'min_selections' => 1, + 'max_selections' => 1, + 'position' => 0, + ]; + } +} diff --git a/packages/bundles/database/migrations/2026_09_15_000000_create_bundles_table.php b/packages/bundles/database/migrations/2026_09_15_000000_create_bundles_table.php new file mode 100644 index 0000000000..8df85e9585 --- /dev/null +++ b/packages/bundles/database/migrations/2026_09_15_000000_create_bundles_table.php @@ -0,0 +1,25 @@ +prefix.'bundles', function (Blueprint $table) { + $table->id(); + $table->ulid('public_id')->unique(); + $table->foreignId('product_variant_id')->unique()->constrained($this->prefix.'product_variants')->cascadeOnDelete(); + $table->string('pricing', 16)->default('fixed'); + $table->decimal('discount_percentage', 5, 2)->nullable(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists($this->prefix.'bundles'); + } +}; diff --git a/packages/bundles/database/migrations/2026_09_15_000001_create_bundle_groups_table.php b/packages/bundles/database/migrations/2026_09_15_000001_create_bundle_groups_table.php new file mode 100644 index 0000000000..472262e0fc --- /dev/null +++ b/packages/bundles/database/migrations/2026_09_15_000001_create_bundle_groups_table.php @@ -0,0 +1,27 @@ +prefix.'bundle_groups', function (Blueprint $table) { + $table->id(); + $table->ulid('public_id')->unique(); + $table->foreignId('bundle_id')->constrained($this->prefix.'bundles')->cascadeOnDelete(); + $table->json('name'); + $table->smallInteger('min_selections')->default(1); + $table->smallInteger('max_selections')->default(1); + $table->smallInteger('position')->default(0); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists($this->prefix.'bundle_groups'); + } +}; diff --git a/packages/bundles/database/migrations/2026_09_15_000002_create_bundle_components_table.php b/packages/bundles/database/migrations/2026_09_15_000002_create_bundle_components_table.php new file mode 100644 index 0000000000..90e14676e2 --- /dev/null +++ b/packages/bundles/database/migrations/2026_09_15_000002_create_bundle_components_table.php @@ -0,0 +1,30 @@ +prefix.'bundle_components', function (Blueprint $table) { + $table->id(); + $table->ulid('public_id')->unique(); + $table->foreignId('bundle_id')->constrained($this->prefix.'bundles')->cascadeOnDelete(); + $table->foreignId('bundle_group_id')->nullable()->constrained($this->prefix.'bundle_groups')->cascadeOnDelete(); + $table->foreignId('product_variant_id')->constrained($this->prefix.'product_variants')->cascadeOnDelete(); + $table->smallInteger('quantity')->default(1); + $table->boolean('default')->default(false); + $table->smallInteger('position')->default(0); + $table->timestamps(); + + $table->unique(['bundle_id', 'bundle_group_id', 'product_variant_id'], 'bundle_components_unique'); + }); + } + + public function down(): void + { + Schema::dropIfExists($this->prefix.'bundle_components'); + } +}; diff --git a/packages/bundles/package.json b/packages/bundles/package.json new file mode 100644 index 0000000000..febdb8729a --- /dev/null +++ b/packages/bundles/package.json @@ -0,0 +1,18 @@ +{ + "name": "@lunarphp/bundles-addon", + "private": true, + "type": "module", + "scripts": { + "build": "vite build", + "dev": "vite" + }, + "devDependencies": { + "@inertiajs/vue3": "^3.0.0", + "@lunarphp/panel": "^0.1.0", + "@lunarphp/panel-vite-plugin": "^0.1.0", + "@vitejs/plugin-vue": "^5.2.0", + "vite": "^6.0.0", + "vue": "^3.5.13", + "vue-i18n": "^11.4.6" + } +} diff --git a/packages/bundles/resources/js/addon.ts b/packages/bundles/resources/js/addon.ts new file mode 100644 index 0000000000..a1452d4e43 --- /dev/null +++ b/packages/bundles/resources/js/addon.ts @@ -0,0 +1,10 @@ +import BundleCard from './components/BundleCard.vue'; +import BundleBadge from './components/BundleBadge.vue'; +import IncludedInBundlesCard from './components/IncludedInBundlesCard.vue'; + +// Registered eagerly: slot and cell components must exist before the panel's first render. +window.LunarPanel.registerComponents('bundles', { + BundleCard, + BundleBadge, + IncludedInBundlesCard, +}); diff --git a/packages/bundles/resources/js/components/BundleBadge.vue b/packages/bundles/resources/js/components/BundleBadge.vue new file mode 100644 index 0000000000..c10b5edafd --- /dev/null +++ b/packages/bundles/resources/js/components/BundleBadge.vue @@ -0,0 +1,14 @@ + + + diff --git a/packages/bundles/resources/js/components/BundleCard.vue b/packages/bundles/resources/js/components/BundleCard.vue new file mode 100644 index 0000000000..c0e12ae830 --- /dev/null +++ b/packages/bundles/resources/js/components/BundleCard.vue @@ -0,0 +1,47 @@ + + + diff --git a/packages/bundles/resources/js/components/BundleEditor.vue b/packages/bundles/resources/js/components/BundleEditor.vue new file mode 100644 index 0000000000..df3004e84f --- /dev/null +++ b/packages/bundles/resources/js/components/BundleEditor.vue @@ -0,0 +1,397 @@ + + + diff --git a/packages/bundles/resources/js/components/ComponentList.vue b/packages/bundles/resources/js/components/ComponentList.vue new file mode 100644 index 0000000000..5a1c2f6fdb --- /dev/null +++ b/packages/bundles/resources/js/components/ComponentList.vue @@ -0,0 +1,99 @@ + + + diff --git a/packages/bundles/resources/js/components/GroupsEditor.vue b/packages/bundles/resources/js/components/GroupsEditor.vue new file mode 100644 index 0000000000..0b1f07a280 --- /dev/null +++ b/packages/bundles/resources/js/components/GroupsEditor.vue @@ -0,0 +1,161 @@ + + + diff --git a/packages/bundles/resources/js/components/IncludedInBundlesCard.vue b/packages/bundles/resources/js/components/IncludedInBundlesCard.vue new file mode 100644 index 0000000000..fc8cc8dd15 --- /dev/null +++ b/packages/bundles/resources/js/components/IncludedInBundlesCard.vue @@ -0,0 +1,57 @@ + + + diff --git a/packages/bundles/resources/js/components/VariantBundleList.vue b/packages/bundles/resources/js/components/VariantBundleList.vue new file mode 100644 index 0000000000..620a2c7551 --- /dev/null +++ b/packages/bundles/resources/js/components/VariantBundleList.vue @@ -0,0 +1,35 @@ + + + diff --git a/packages/bundles/resources/js/components/VariantThumb.vue b/packages/bundles/resources/js/components/VariantThumb.vue new file mode 100644 index 0000000000..d90b15df80 --- /dev/null +++ b/packages/bundles/resources/js/components/VariantThumb.vue @@ -0,0 +1,23 @@ + + + diff --git a/packages/bundles/resources/js/types.ts b/packages/bundles/resources/js/types.ts new file mode 100644 index 0000000000..c24f659ab6 --- /dev/null +++ b/packages/bundles/resources/js/types.ts @@ -0,0 +1,82 @@ +export interface VariantRow { + id: number; + public_id: string; + sku: string | null; + name: string; + option: string | null; + thumbnail: string | null; + edit_url: string; +} + +export interface BundleComponentRow { + id: number; + public_id: string; + group_id: number | null; + quantity: number; + default: boolean; + position: number; + variant: VariantRow; +} + +export interface BundleGroupRow { + id: number; + public_id: string; + name: Record; + label: string; + min_selections: number; + max_selections: number; + position: number; +} + +export interface DerivedPrice { + currency: string; + price: string | null; + list_price: string | null; + missing: string[]; +} + +export interface BundleDefinition { + id: number; + pricing: 'fixed' | 'components'; + discount_percentage: number | null; + configurable: boolean; + components: BundleComponentRow[]; + groups: BundleGroupRow[]; + availability: { available: number; unlimited: boolean }; + prices: DerivedPrice[]; +} + +export interface BundleSummary { + variant: VariantRow; + defined: boolean; + bundle: BundleDefinition | null; + default_language: string; + urls: { + show: string; + define: string; + destroy: string; + components: string; + groups: string; + search: string; + }; +} + +/** What the sync endpoints accept; every call sends the complete list. */ +export interface ComponentPayload { + variant_id: number; + quantity: number; + group_id: number | null; + default: boolean; + position: number; +} + +export interface GroupPayload { + id: number | null; + name: Record; + min_selections: number; + max_selections: number; + position: number; +} + +export const panelPath = (props: Record): string => + (props.panel as { path?: string } | undefined)?.path ?? 'panel'; diff --git a/packages/bundles/resources/lang/ar/bundles.php b/packages/bundles/resources/lang/ar/bundles.php new file mode 100644 index 0000000000..ff6e4fd21c --- /dev/null +++ b/packages/bundles/resources/lang/ar/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'اختيار الحزمة غير صالح.', + 'unknown_group' => 'لا تحتوي الحزمة على مجموعة الخيارات ":id".', + 'unknown_component' => 'الخيار ":id" غير متاح في ":group".', + 'duplicate_component' => 'تم اختيار خيار في ":group" أكثر من مرة.', + 'count' => 'اختر بين :min و :max من الخيارات في ":group".', + 'unavailable' => 'مكوّن الحزمة ":identifier" غير متاح بهذه الكمية.', + ], + 'nesting' => [ + 'is_component' => 'لا يمكن لمتغير يشكّل جزءاً من حزمة أخرى أن يكون حزمة بنفسه.', + 'is_bundle' => 'لا يمكن للحزمة أن تحتوي على حزمة أخرى.', + 'self' => 'لا يمكن للحزمة أن تحتوي على متغيرها الخاص.', + ], + 'definition' => [ + 'empty' => 'تحتاج الحزمة إلى مكوّن واحد على الأقل.', + 'too_many_components' => 'لا يمكن أن تحتوي الحزمة على أكثر من :max مكوّنات.', + 'unknown_group' => 'مجموعة الخيارات لا تنتمي إلى هذه الحزمة.', + 'group_selections' => 'يجب أن تستوفي حدود الاختيار لـ ":group" الشرط: الحد الأدنى <= الحد الأقصى <= عدد الخيارات.', + ], + 'pricing' => [ + 'missing_component_price' => 'المكوّن ":identifier" ليس له سعر بعملة :currency، لذلك لا يمكن تسعير الحزمة بهذه العملة.', + ], + 'panel' => [ + 'column_bundle' => 'حزمة', + 'badge_bundle' => 'حزمة', + 'filter_label' => 'الحزم', + 'filter_only' => 'الحزم فقط', + 'not_defined' => 'هذا المتغير لا يُباع كحزمة.', + 'card_title' => 'حزمة', + 'card_description' => 'بيع هذا المتغير كمجموعة من متغيرات أخرى. يُشتق المخزون من المكوّنات، ويُجهَّز كل مكوّن ويُنفَّذ من الطلب.', + 'sell_as_bundle' => 'البيع كحزمة', + 'confirm_remove_title' => 'إيقاف البيع كحزمة؟', + 'confirm_remove' => 'ستُحذف قائمة المكوّنات ومجموعات الخيارات. يحتفظ المتغير بأسعاره ويعود متغيرًا عاديًا.', + 'confirm_components_title' => 'التسعير من المكونات؟', + 'confirm_components' => 'تُستبدل الأسعار الأساسية الخاصة بالمتغير بمجموع مكوناته وتُعاد كتابتها كلما تغير سعر أحد المكونات. عد إلى السعر الثابت لتحديدها يدويًا مرة أخرى.', + 'pricing' => 'التسعير', + 'pricing_fixed' => 'سعر ثابت', + 'pricing_components' => 'مجموع المكوّنات', + 'discount_percentage' => 'الخصم', + 'discount_hint' => 'يُخصم من إجمالي المكوّنات.', + 'derived_note' => 'في هذا الوضع تُشتق الأسعار من المكوّنات وتُستبدل عند كل إعادة تسعير للحزمة. بدّل إلى السعر الثابت لتحديدها يدويًا.', + 'components' => 'المكوّنات', + 'components_description' => 'مضمّنة دائمًا، بهذا الترتيب.', + 'components_empty' => 'لا توجد مكوّنات بعد. أضف مكوّنًا واحدًا على الأقل ليصبح بيع الحزمة ممكنًا.', + 'add_component' => 'إضافة مكوّن', + 'quantity' => 'الكمية', + 'move_up' => 'نقل لأعلى', + 'move_down' => 'نقل لأسفل', + 'remove' => 'إزالة', + 'availability' => 'التوفر', + 'availability_count' => 'يمكن بيع {count} من مخزون المكوّنات.', + 'availability_unlimited' => 'غير مقيّد بمخزون المكوّنات.', + 'availability_none' => 'غير متوفر: أحد المكوّنات غير متاح.', + 'derived_prices' => 'الأسعار المشتقة', + 'price' => 'السعر', + 'list_price' => 'السعر السابق', + 'missing_price' => 'لا يوجد سعر لـ: {components}', + 'groups' => 'مجموعات الخيارات', + 'groups_description' => 'دع المتسوق يختار من مجموعة من المكوّنات. الحزمة بلا مجموعات تكون ثابتة.', + 'add_group' => 'إضافة مجموعة', + 'group_name' => 'اسم المجموعة', + 'group_min' => 'الحد الأدنى', + 'group_max' => 'الحد الأقصى', + 'group_default' => 'افتراضي', + 'group_empty' => 'لا توجد خيارات في هذه المجموعة بعد.', + 'add_option' => 'إضافة خيار', + 'remove_group' => 'إزالة المجموعة', + 'confirm_remove_group' => 'إزالة هذه المجموعة وخياراتها؟', + 'new_group_name' => 'مجموعة جديدة', + 'saved' => 'تم حفظ الحزمة.', + 'removed' => 'تمت إزالة الحزمة.', + 'load_failed' => 'تعذّر تحميل الحزمة.', + 'variant_summary_description' => 'تُعرَّف الحزم لكل متغير على حدة. افتح متغيرًا لتعديل مكوّناته.', + 'variant_component_count' => '{count} مكوّن | {count} مكوّنات', + 'variant_not_bundle' => 'ليست حزمة', + 'edit_variant' => 'تعديل المتغير', + 'included_in_title' => 'مضمّن في الحزم', + 'included_in_description' => 'حذف متغير يزيله من هذه الحزم.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => 'تمت إعادة تسعير :count حزمة.', + ], +]; diff --git a/packages/bundles/resources/lang/bg/bundles.php b/packages/bundles/resources/lang/bg/bundles.php new file mode 100644 index 0000000000..2e35fcf860 --- /dev/null +++ b/packages/bundles/resources/lang/bg/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'Изборът на комплекта е невалиден.', + 'unknown_group' => 'Комплектът няма група с опции ":id".', + 'unknown_component' => 'Опцията ":id" не е налична в ":group".', + 'duplicate_component' => 'Опция в ":group" е избрана повече от веднъж.', + 'count' => 'Изберете между :min и :max опции в ":group".', + 'unavailable' => 'Компонентът на комплекта ":identifier" не е наличен в това количество.', + ], + 'nesting' => [ + 'is_component' => 'Вариант, който е част от друг комплект, не може сам да бъде комплект.', + 'is_bundle' => 'Комплектът не може да съдържа друг комплект.', + 'self' => 'Комплектът не може да съдържа собствения си вариант.', + ], + 'definition' => [ + 'empty' => 'Комплектът се нуждае от поне един компонент.', + 'too_many_components' => 'Комплектът не може да има повече от :max компонента.', + 'unknown_group' => 'Групата с опции не принадлежи на този комплект.', + 'group_selections' => 'Границите за избор на ":group" трябва да отговарят на минимум <= максимум <= брой опции.', + ], + 'pricing' => [ + 'missing_component_price' => 'Компонентът ":identifier" няма цена в :currency, затова комплектът не може да бъде оценен в тази валута.', + ], + 'panel' => [ + 'column_bundle' => 'Комплект', + 'badge_bundle' => 'Комплект', + 'filter_label' => 'Комплекти', + 'filter_only' => 'Само комплекти', + 'not_defined' => 'Този вариант не се продава като комплект.', + 'card_title' => 'Комплект', + 'card_description' => 'Продавайте този вариант като набор от други варианти. Наличността се извежда от компонентите и всеки компонент се събира и изпълнява от поръчката.', + 'sell_as_bundle' => 'Продавай като комплект', + 'confirm_remove_title' => 'Да се спре продажбата като комплект?', + 'confirm_remove' => 'Списъкът с компоненти и групите с опции ще бъдат премахнати. Вариантът запазва цените си и отново става обикновен вариант.', + 'confirm_components_title' => 'Цена от компонентите?', + 'confirm_components' => 'Собствените базови цени на варианта се заменят със сумата от компонентите му и се презаписват при всяка промяна на цената на компонент. Върнете се към фиксирана цена, за да ги задавате ръчно отново.', + 'pricing' => 'Ценообразуване', + 'pricing_fixed' => 'Фиксирана цена', + 'pricing_components' => 'Сума на компонентите', + 'discount_percentage' => 'Отстъпка', + 'discount_hint' => 'Приспада се от сумата на компонентите.', + 'derived_note' => 'В този режим цените се извеждат от компонентите и се презаписват при всяко преизчисляване на комплекта. Превключете на фиксирана цена, за да ги зададете ръчно.', + 'components' => 'Компоненти', + 'components_description' => 'Винаги включени, в този ред.', + 'components_empty' => 'Все още няма компоненти. Добавете поне един, за да може комплектът да се продава.', + 'add_component' => 'Добави компонент', + 'quantity' => 'Кол.', + 'move_up' => 'Премести нагоре', + 'move_down' => 'Премести надолу', + 'remove' => 'Премахни', + 'availability' => 'Наличност', + 'availability_count' => 'От наличността на компонентите могат да се продадат {count}.', + 'availability_unlimited' => 'Не е ограничено от наличността на компонентите.', + 'availability_none' => 'Изчерпано: един компонент не е наличен.', + 'derived_prices' => 'Изведени цени', + 'price' => 'Цена', + 'list_price' => 'Преди', + 'missing_price' => 'Няма цена за: {components}', + 'groups' => 'Групи с опции', + 'groups_description' => 'Позволете на клиента да избира от набор компоненти. Комплект без групи е фиксиран.', + 'add_group' => 'Добави група', + 'group_name' => 'Име на групата', + 'group_min' => 'Мин.', + 'group_max' => 'Макс.', + 'group_default' => 'По подразбиране', + 'group_empty' => 'Все още няма опции в тази група.', + 'add_option' => 'Добави опция', + 'remove_group' => 'Премахни групата', + 'confirm_remove_group' => 'Да се премахне тази група и опциите ѝ?', + 'new_group_name' => 'Нова група', + 'saved' => 'Комплектът е запазен.', + 'removed' => 'Комплектът е премахнат.', + 'load_failed' => 'Комплектът не можа да бъде зареден.', + 'variant_summary_description' => 'Комплектите се дефинират за всеки вариант. Отворете вариант, за да редактирате компонентите му.', + 'variant_component_count' => '{count} компонент | {count} компонента', + 'variant_not_bundle' => 'Не е комплект', + 'edit_variant' => 'Редактирай варианта', + 'included_in_title' => 'Включен в комплекти', + 'included_in_description' => 'Изтриването на вариант го премахва от тези комплекти.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => 'Преизчислени са цените на :count комплекта.', + ], +]; diff --git a/packages/bundles/resources/lang/de/bundles.php b/packages/bundles/resources/lang/de/bundles.php new file mode 100644 index 0000000000..803c455ffb --- /dev/null +++ b/packages/bundles/resources/lang/de/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'Die Bundle-Auswahl ist fehlerhaft.', + 'unknown_group' => 'Das Bundle hat keine Optionsgruppe ":id".', + 'unknown_component' => 'Option ":id" ist in ":group" nicht verfügbar.', + 'duplicate_component' => 'Eine Option in ":group" wurde mehrfach gewählt.', + 'count' => 'Wählen Sie zwischen :min und :max Optionen in ":group".', + 'unavailable' => 'Bundle-Komponente ":identifier" ist in dieser Menge nicht verfügbar.', + ], + 'nesting' => [ + 'is_component' => 'Eine Variante, die Teil eines anderen Bundles ist, kann selbst kein Bundle sein.', + 'is_bundle' => 'Ein Bundle kann kein anderes Bundle enthalten.', + 'self' => 'Ein Bundle kann nicht seine eigene Variante enthalten.', + ], + 'definition' => [ + 'empty' => 'Ein Bundle benötigt mindestens eine Komponente.', + 'too_many_components' => 'Ein Bundle darf nicht mehr als :max Komponenten haben.', + 'unknown_group' => 'Die Optionsgruppe gehört nicht zu diesem Bundle.', + 'group_selections' => 'Die Auswahlgrenzen für ":group" müssen Minimum <= Maximum <= Anzahl der Optionen erfüllen.', + ], + 'pricing' => [ + 'missing_component_price' => 'Komponente ":identifier" hat keinen Preis in :currency, daher kann das Bundle in dieser Währung nicht bepreist werden.', + ], + 'panel' => [ + 'column_bundle' => 'Bundle', + 'badge_bundle' => 'Bundle', + 'filter_label' => 'Bundles', + 'filter_only' => 'Nur Bundles', + 'not_defined' => 'Diese Variante wird nicht als Bundle verkauft.', + 'card_title' => 'Bundle', + 'card_description' => 'Diese Variante als Zusammenstellung anderer Varianten verkaufen. Der Bestand wird aus den Komponenten abgeleitet und jede Komponente wird aus der Bestellung kommissioniert und erfüllt.', + 'sell_as_bundle' => 'Als Bundle verkaufen', + 'confirm_remove_title' => 'Nicht mehr als Bundle verkaufen?', + 'confirm_remove' => 'Die Komponentenliste und die Optionsgruppen werden entfernt. Die Variante behält ihre Preise und wird wieder eine gewöhnliche Variante.', + 'confirm_components_title' => 'Preis aus den Komponenten bilden?', + 'confirm_components' => 'Die eigenen Grundpreise der Variante werden durch die Summe ihrer Komponenten ersetzt und bei jeder Preisänderung einer Komponente neu geschrieben. Wechseln Sie zurück zum Festpreis, um sie wieder von Hand zu setzen.', + 'pricing' => 'Preisgestaltung', + 'pricing_fixed' => 'Festpreis', + 'pricing_components' => 'Summe der Komponenten', + 'discount_percentage' => 'Rabatt', + 'discount_hint' => 'Wird von der Komponentensumme abgezogen.', + 'derived_note' => 'Preise in diesem Modus werden aus den Komponenten abgeleitet und bei jeder Neuberechnung überschrieben. Wechseln Sie zum Festpreis, um sie manuell festzulegen.', + 'components' => 'Komponenten', + 'components_description' => 'Immer enthalten, in dieser Reihenfolge.', + 'components_empty' => 'Noch keine Komponenten. Fügen Sie mindestens eine hinzu, damit das Bundle verkauft werden kann.', + 'add_component' => 'Komponente hinzufügen', + 'quantity' => 'Menge', + 'move_up' => 'Nach oben', + 'move_down' => 'Nach unten', + 'remove' => 'Entfernen', + 'availability' => 'Verfügbarkeit', + 'availability_count' => '{count} können aus dem Komponentenbestand verkauft werden.', + 'availability_unlimited' => 'Nicht durch den Komponentenbestand begrenzt.', + 'availability_none' => 'Nicht auf Lager: eine Komponente ist nicht verfügbar.', + 'derived_prices' => 'Abgeleitete Preise', + 'price' => 'Preis', + 'list_price' => 'Vorher', + 'missing_price' => 'Kein Preis für: {components}', + 'groups' => 'Optionsgruppen', + 'groups_description' => 'Lassen Sie Kunden aus einer Auswahl von Komponenten wählen. Ein Bundle ohne Gruppen ist fest.', + 'add_group' => 'Gruppe hinzufügen', + 'group_name' => 'Gruppenname', + 'group_min' => 'Min.', + 'group_max' => 'Max.', + 'group_default' => 'Standard', + 'group_empty' => 'Noch keine Optionen in dieser Gruppe.', + 'add_option' => 'Option hinzufügen', + 'remove_group' => 'Gruppe entfernen', + 'confirm_remove_group' => 'Diese Gruppe und ihre Optionen entfernen?', + 'new_group_name' => 'Neue Gruppe', + 'saved' => 'Bundle gespeichert.', + 'removed' => 'Bundle entfernt.', + 'load_failed' => 'Das Bundle konnte nicht geladen werden.', + 'variant_summary_description' => 'Bundles werden pro Variante definiert. Öffnen Sie eine Variante, um ihre Komponenten zu bearbeiten.', + 'variant_component_count' => '{count} Komponente | {count} Komponenten', + 'variant_not_bundle' => 'Kein Bundle', + 'edit_variant' => 'Variante bearbeiten', + 'included_in_title' => 'Enthalten in Bundles', + 'included_in_description' => 'Beim Löschen einer Variante wird sie aus diesen Bundles entfernt.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => ':count Bundles neu bepreist.', + ], +]; diff --git a/packages/bundles/resources/lang/en/bundles.php b/packages/bundles/resources/lang/en/bundles.php new file mode 100644 index 0000000000..e8ee23592b --- /dev/null +++ b/packages/bundles/resources/lang/en/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'The bundle selection is malformed.', + 'unknown_group' => 'The bundle has no option group ":id".', + 'unknown_component' => 'Option ":id" is not available in ":group".', + 'duplicate_component' => 'An option in ":group" was chosen more than once.', + 'count' => 'Choose between :min and :max options in ":group".', + 'unavailable' => 'Bundle component ":identifier" is not available at this quantity.', + ], + 'nesting' => [ + 'is_component' => 'A variant that is part of another bundle cannot be a bundle itself.', + 'is_bundle' => 'A bundle cannot contain another bundle.', + 'self' => 'A bundle cannot contain its own variant.', + ], + 'definition' => [ + 'empty' => 'A bundle needs at least one component.', + 'too_many_components' => 'A bundle cannot have more than :max components.', + 'unknown_group' => 'The option group does not belong to this bundle.', + 'group_selections' => 'The selection limits for ":group" must satisfy minimum <= maximum <= number of options.', + ], + 'pricing' => [ + 'missing_component_price' => 'Component ":identifier" has no price in :currency, so the bundle cannot be priced in that currency.', + ], + 'panel' => [ + 'column_bundle' => 'Bundle', + 'badge_bundle' => 'Bundle', + 'filter_label' => 'Bundles', + 'filter_only' => 'Bundles only', + 'not_defined' => 'This variant is not sold as a bundle.', + 'card_title' => 'Bundle', + 'card_description' => 'Sell this variant as a set of other variants. Stock is derived from the components and each component is picked and fulfilled from the order.', + 'sell_as_bundle' => 'Sell as a bundle', + 'confirm_remove_title' => 'Stop selling as a bundle?', + 'confirm_remove' => 'The component list and option groups are removed. The variant keeps its prices and becomes an ordinary variant.', + 'confirm_components_title' => 'Price from the components?', + 'confirm_components' => 'The variant\'s own base prices are replaced by the sum of its components and rewritten whenever a component\'s price changes. Switch back to a fixed price to set them by hand again.', + 'pricing' => 'Pricing', + 'pricing_fixed' => 'Fixed price', + 'pricing_components' => 'Sum of components', + 'discount_percentage' => 'Discount', + 'discount_hint' => 'Taken off the component total.', + 'derived_note' => 'Prices in this mode are derived from the components and overwritten whenever the bundle is repriced. Switch to a fixed price to set them by hand.', + 'components' => 'Components', + 'components_description' => 'Always included, in this order.', + 'components_empty' => 'No components yet. Add at least one to make the bundle sellable.', + 'add_component' => 'Add component', + 'quantity' => 'Qty', + 'move_up' => 'Move up', + 'move_down' => 'Move down', + 'remove' => 'Remove', + 'availability' => 'Availability', + 'availability_count' => '{count} can be sold from component stock.', + 'availability_unlimited' => 'Not limited by component stock.', + 'availability_none' => 'Out of stock: a component is unavailable.', + 'derived_prices' => 'Derived prices', + 'price' => 'Price', + 'list_price' => 'Was', + 'missing_price' => 'No price for: {components}', + 'groups' => 'Option groups', + 'groups_description' => 'Let the shopper choose from a set of components. A bundle with no groups is fixed.', + 'add_group' => 'Add group', + 'group_name' => 'Group name', + 'group_min' => 'Min', + 'group_max' => 'Max', + 'group_default' => 'Default', + 'group_empty' => 'No options in this group yet.', + 'add_option' => 'Add option', + 'remove_group' => 'Remove group', + 'confirm_remove_group' => 'Remove this group and its options?', + 'new_group_name' => 'New group', + 'saved' => 'Bundle saved.', + 'removed' => 'Bundle removed.', + 'load_failed' => 'The bundle could not be loaded.', + 'variant_summary_description' => 'Bundles are defined per variant. Open a variant to edit its components.', + 'variant_component_count' => '{count} component | {count} components', + 'variant_not_bundle' => 'Not a bundle', + 'edit_variant' => 'Edit variant', + 'included_in_title' => 'Included in bundles', + 'included_in_description' => 'Deleting a variant removes it from these bundles.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => 'Repriced :count bundles.', + ], +]; diff --git a/packages/bundles/resources/lang/es/bundles.php b/packages/bundles/resources/lang/es/bundles.php new file mode 100644 index 0000000000..307925a3e2 --- /dev/null +++ b/packages/bundles/resources/lang/es/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'La selección del paquete no es válida.', + 'unknown_group' => 'El paquete no tiene ningún grupo de opciones ":id".', + 'unknown_component' => 'La opción ":id" no está disponible en ":group".', + 'duplicate_component' => 'Una opción de ":group" se eligió más de una vez.', + 'count' => 'Elige entre :min y :max opciones en ":group".', + 'unavailable' => 'El componente del paquete ":identifier" no está disponible en esta cantidad.', + ], + 'nesting' => [ + 'is_component' => 'Una variante que forma parte de otro paquete no puede ser un paquete.', + 'is_bundle' => 'Un paquete no puede contener otro paquete.', + 'self' => 'Un paquete no puede contener su propia variante.', + ], + 'definition' => [ + 'empty' => 'Un paquete necesita al menos un componente.', + 'too_many_components' => 'Un paquete no puede tener más de :max componentes.', + 'unknown_group' => 'El grupo de opciones no pertenece a este paquete.', + 'group_selections' => 'Los límites de selección de ":group" deben cumplir mínimo <= máximo <= número de opciones.', + ], + 'pricing' => [ + 'missing_component_price' => 'El componente ":identifier" no tiene precio en :currency, por lo que el paquete no se puede valorar en esa moneda.', + ], + 'panel' => [ + 'column_bundle' => 'Paquete', + 'badge_bundle' => 'Paquete', + 'filter_label' => 'Paquetes', + 'filter_only' => 'Solo paquetes', + 'not_defined' => 'Esta variante no se vende como paquete.', + 'card_title' => 'Paquete', + 'card_description' => 'Vende esta variante como un conjunto de otras variantes. El stock se deriva de los componentes y cada componente se prepara y se entrega desde el pedido.', + 'sell_as_bundle' => 'Vender como paquete', + 'confirm_remove_title' => '¿Dejar de vender como paquete?', + 'confirm_remove' => 'Se eliminan la lista de componentes y los grupos de opciones. La variante conserva sus precios y vuelve a ser una variante normal.', + 'confirm_components_title' => '¿Calcular el precio a partir de los componentes?', + 'confirm_components' => 'Los precios base propios de la variante se sustituyen por la suma de sus componentes y se reescriben cada vez que cambia el precio de un componente. Vuelva al precio fijo para definirlos a mano de nuevo.', + 'pricing' => 'Precio', + 'pricing_fixed' => 'Precio fijo', + 'pricing_components' => 'Suma de los componentes', + 'discount_percentage' => 'Descuento', + 'discount_hint' => 'Se resta del total de los componentes.', + 'derived_note' => 'En este modo los precios se derivan de los componentes y se sobrescriben cada vez que se recalcula el paquete. Cambia a precio fijo para definirlos a mano.', + 'components' => 'Componentes', + 'components_description' => 'Siempre incluidos, en este orden.', + 'components_empty' => 'Todavía no hay componentes. Añade al menos uno para que el paquete se pueda vender.', + 'add_component' => 'Añadir componente', + 'quantity' => 'Cant.', + 'move_up' => 'Subir', + 'move_down' => 'Bajar', + 'remove' => 'Quitar', + 'availability' => 'Disponibilidad', + 'availability_count' => 'Se pueden vender {count} con el stock de los componentes.', + 'availability_unlimited' => 'No está limitado por el stock de los componentes.', + 'availability_none' => 'Agotado: un componente no está disponible.', + 'derived_prices' => 'Precios derivados', + 'price' => 'Precio', + 'list_price' => 'Antes', + 'missing_price' => 'Sin precio para: {components}', + 'groups' => 'Grupos de opciones', + 'groups_description' => 'Deja que el cliente elija entre un conjunto de componentes. Un paquete sin grupos es fijo.', + 'add_group' => 'Añadir grupo', + 'group_name' => 'Nombre del grupo', + 'group_min' => 'Mín.', + 'group_max' => 'Máx.', + 'group_default' => 'Predeterminado', + 'group_empty' => 'Todavía no hay opciones en este grupo.', + 'add_option' => 'Añadir opción', + 'remove_group' => 'Quitar grupo', + 'confirm_remove_group' => '¿Quitar este grupo y sus opciones?', + 'new_group_name' => 'Nuevo grupo', + 'saved' => 'Paquete guardado.', + 'removed' => 'Paquete eliminado.', + 'load_failed' => 'No se pudo cargar el paquete.', + 'variant_summary_description' => 'Los paquetes se definen por variante. Abre una variante para editar sus componentes.', + 'variant_component_count' => '{count} componente | {count} componentes', + 'variant_not_bundle' => 'No es un paquete', + 'edit_variant' => 'Editar variante', + 'included_in_title' => 'Incluido en paquetes', + 'included_in_description' => 'Al eliminar una variante se quita de estos paquetes.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => 'Se han recalculado los precios de :count paquetes.', + ], +]; diff --git a/packages/bundles/resources/lang/fa/bundles.php b/packages/bundles/resources/lang/fa/bundles.php new file mode 100644 index 0000000000..f2b5fd234b --- /dev/null +++ b/packages/bundles/resources/lang/fa/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'انتخاب بسته نامعتبر است.', + 'unknown_group' => 'بسته گروه گزینه ":id" را ندارد.', + 'unknown_component' => 'گزینه ":id" در ":group" موجود نیست.', + 'duplicate_component' => 'یک گزینه در ":group" بیش از یک بار انتخاب شده است.', + 'count' => 'بین :min تا :max گزینه در ":group" انتخاب کنید.', + 'unavailable' => 'جزء بسته ":identifier" با این تعداد موجود نیست.', + ], + 'nesting' => [ + 'is_component' => 'گونه‌ای که بخشی از بسته دیگری است نمی‌تواند خود یک بسته باشد.', + 'is_bundle' => 'یک بسته نمی‌تواند بسته دیگری را شامل شود.', + 'self' => 'یک بسته نمی‌تواند گونه خودش را شامل شود.', + ], + 'definition' => [ + 'empty' => 'یک بسته به حداقل یک جزء نیاز دارد.', + 'too_many_components' => 'یک بسته نمی‌تواند بیش از :max جزء داشته باشد.', + 'unknown_group' => 'گروه گزینه به این بسته تعلق ندارد.', + 'group_selections' => 'محدودیت‌های انتخاب برای ":group" باید شرط حداقل <= حداکثر <= تعداد گزینه‌ها را برآورده کنند.', + ], + 'pricing' => [ + 'missing_component_price' => 'جزء ":identifier" قیمتی به :currency ندارد، بنابراین بسته با این ارز قابل قیمت‌گذاری نیست.', + ], + 'panel' => [ + 'column_bundle' => 'بسته', + 'badge_bundle' => 'بسته', + 'filter_label' => 'بسته‌ها', + 'filter_only' => 'فقط بسته‌ها', + 'not_defined' => 'این گونه به‌صورت بسته فروخته نمی‌شود.', + 'card_title' => 'بسته', + 'card_description' => 'این گونه را به‌صورت مجموعه‌ای از گونه‌های دیگر بفروشید. موجودی از اجزا محاسبه می‌شود و هر جزء از سفارش آماده و تحویل می‌شود.', + 'sell_as_bundle' => 'فروش به‌صورت بسته', + 'confirm_remove_title' => 'فروش به‌صورت بسته متوقف شود؟', + 'confirm_remove' => 'فهرست اجزا و گروه‌های گزینه حذف می‌شوند. گونه قیمت‌های خود را نگه می‌دارد و دوباره یک گونه عادی می‌شود.', + 'confirm_components_title' => 'قیمت از اجزا محاسبه شود؟', + 'confirm_components' => 'قیمت‌های پایه خود گونه با مجموع اجزای آن جایگزین می‌شود و هر بار که قیمت یکی از اجزا تغییر کند دوباره نوشته می‌شود. برای تعیین دستی دوباره، به قیمت ثابت برگردید.', + 'pricing' => 'قیمت‌گذاری', + 'pricing_fixed' => 'قیمت ثابت', + 'pricing_components' => 'مجموع اجزا', + 'discount_percentage' => 'تخفیف', + 'discount_hint' => 'از مجموع اجزا کسر می‌شود.', + 'derived_note' => 'در این حالت قیمت‌ها از اجزا محاسبه می‌شوند و با هر بار قیمت‌گذاری مجدد بسته بازنویسی می‌شوند. برای تنظیم دستی به قیمت ثابت تغییر دهید.', + 'components' => 'اجزا', + 'components_description' => 'همیشه شامل می‌شوند، به این ترتیب.', + 'components_empty' => 'هنوز جزئی وجود ندارد. حداقل یک جزء اضافه کنید تا بسته قابل فروش شود.', + 'add_component' => 'افزودن جزء', + 'quantity' => 'تعداد', + 'move_up' => 'انتقال به بالا', + 'move_down' => 'انتقال به پایین', + 'remove' => 'حذف', + 'availability' => 'موجودی', + 'availability_count' => '{count} عدد از موجودی اجزا قابل فروش است.', + 'availability_unlimited' => 'محدود به موجودی اجزا نیست.', + 'availability_none' => 'ناموجود: یکی از اجزا در دسترس نیست.', + 'derived_prices' => 'قیمت‌های محاسبه‌شده', + 'price' => 'قیمت', + 'list_price' => 'قیمت قبلی', + 'missing_price' => 'قیمتی برای این موارد وجود ندارد: {components}', + 'groups' => 'گروه‌های گزینه', + 'groups_description' => 'به خریدار اجازه دهید از میان مجموعه‌ای از اجزا انتخاب کند. بسته بدون گروه، ثابت است.', + 'add_group' => 'افزودن گروه', + 'group_name' => 'نام گروه', + 'group_min' => 'حداقل', + 'group_max' => 'حداکثر', + 'group_default' => 'پیش‌فرض', + 'group_empty' => 'هنوز گزینه‌ای در این گروه وجود ندارد.', + 'add_option' => 'افزودن گزینه', + 'remove_group' => 'حذف گروه', + 'confirm_remove_group' => 'این گروه و گزینه‌هایش حذف شوند؟', + 'new_group_name' => 'گروه جدید', + 'saved' => 'بسته ذخیره شد.', + 'removed' => 'بسته حذف شد.', + 'load_failed' => 'بارگذاری بسته ممکن نشد.', + 'variant_summary_description' => 'بسته‌ها برای هر گونه جداگانه تعریف می‌شوند. برای ویرایش اجزا، یک گونه را باز کنید.', + 'variant_component_count' => '{count} جزء | {count} جزء', + 'variant_not_bundle' => 'بسته نیست', + 'edit_variant' => 'ویرایش گونه', + 'included_in_title' => 'موجود در بسته‌ها', + 'included_in_description' => 'حذف یک گونه آن را از این بسته‌ها حذف می‌کند.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => 'قیمت :count بسته دوباره محاسبه شد.', + ], +]; diff --git a/packages/bundles/resources/lang/fr/bundles.php b/packages/bundles/resources/lang/fr/bundles.php new file mode 100644 index 0000000000..09498395b4 --- /dev/null +++ b/packages/bundles/resources/lang/fr/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'La sélection du lot est mal formée.', + 'unknown_group' => 'Le lot n\'a pas de groupe d\'options ":id".', + 'unknown_component' => 'L\'option ":id" n\'est pas disponible dans ":group".', + 'duplicate_component' => 'Une option de ":group" a été choisie plusieurs fois.', + 'count' => 'Choisissez entre :min et :max options dans ":group".', + 'unavailable' => 'Le composant du lot ":identifier" n\'est pas disponible en cette quantité.', + ], + 'nesting' => [ + 'is_component' => 'Une variante faisant partie d\'un autre lot ne peut pas être elle-même un lot.', + 'is_bundle' => 'Un lot ne peut pas contenir un autre lot.', + 'self' => 'Un lot ne peut pas contenir sa propre variante.', + ], + 'definition' => [ + 'empty' => 'Un lot doit contenir au moins un composant.', + 'too_many_components' => 'Un lot ne peut pas contenir plus de :max composants.', + 'unknown_group' => 'Le groupe d\'options n\'appartient pas à ce lot.', + 'group_selections' => 'Les limites de sélection de ":group" doivent respecter minimum <= maximum <= nombre d\'options.', + ], + 'pricing' => [ + 'missing_component_price' => 'Le composant ":identifier" n\'a pas de prix en :currency, le lot ne peut donc pas être tarifé dans cette devise.', + ], + 'panel' => [ + 'column_bundle' => 'Lot', + 'badge_bundle' => 'Lot', + 'filter_label' => 'Lots', + 'filter_only' => 'Lots uniquement', + 'not_defined' => 'Cette variante n\'est pas vendue comme un lot.', + 'card_title' => 'Lot', + 'card_description' => 'Vendre cette variante comme un ensemble d\'autres variantes. Le stock est dérivé des composants et chaque composant est préparé et expédié depuis la commande.', + 'sell_as_bundle' => 'Vendre comme un lot', + 'confirm_remove_title' => 'Ne plus vendre comme un lot ?', + 'confirm_remove' => 'La liste des composants et les groupes d\'options sont supprimés. La variante conserve ses prix et redevient une variante ordinaire.', + 'confirm_components_title' => 'Calculer le prix a partir des composants ?', + 'confirm_components' => 'Les prix de base propres a la variante sont remplaces par la somme de ses composants et reecrits a chaque changement de prix d\'un composant. Revenez au prix fixe pour les definir a nouveau a la main.', + 'pricing' => 'Tarification', + 'pricing_fixed' => 'Prix fixe', + 'pricing_components' => 'Somme des composants', + 'discount_percentage' => 'Remise', + 'discount_hint' => 'Déduite du total des composants.', + 'derived_note' => 'Dans ce mode, les prix sont dérivés des composants et écrasés à chaque recalcul. Passez au prix fixe pour les définir à la main.', + 'components' => 'Composants', + 'components_description' => 'Toujours inclus, dans cet ordre.', + 'components_empty' => 'Aucun composant pour l\'instant. Ajoutez-en au moins un pour que le lot soit vendable.', + 'add_component' => 'Ajouter un composant', + 'quantity' => 'Qté', + 'move_up' => 'Monter', + 'move_down' => 'Descendre', + 'remove' => 'Retirer', + 'availability' => 'Disponibilité', + 'availability_count' => '{count} peuvent être vendus à partir du stock des composants.', + 'availability_unlimited' => 'Non limité par le stock des composants.', + 'availability_none' => 'En rupture : un composant est indisponible.', + 'derived_prices' => 'Prix dérivés', + 'price' => 'Prix', + 'list_price' => 'Avant', + 'missing_price' => 'Aucun prix pour : {components}', + 'groups' => 'Groupes d\'options', + 'groups_description' => 'Laissez le client choisir parmi un ensemble de composants. Un lot sans groupe est fixe.', + 'add_group' => 'Ajouter un groupe', + 'group_name' => 'Nom du groupe', + 'group_min' => 'Min', + 'group_max' => 'Max', + 'group_default' => 'Par défaut', + 'group_empty' => 'Aucune option dans ce groupe pour l\'instant.', + 'add_option' => 'Ajouter une option', + 'remove_group' => 'Retirer le groupe', + 'confirm_remove_group' => 'Retirer ce groupe et ses options ?', + 'new_group_name' => 'Nouveau groupe', + 'saved' => 'Lot enregistré.', + 'removed' => 'Lot supprimé.', + 'load_failed' => 'Le lot n\'a pas pu être chargé.', + 'variant_summary_description' => 'Les lots se définissent par variante. Ouvrez une variante pour modifier ses composants.', + 'variant_component_count' => '{count} composant | {count} composants', + 'variant_not_bundle' => 'Pas un lot', + 'edit_variant' => 'Modifier la variante', + 'included_in_title' => 'Inclus dans des lots', + 'included_in_description' => 'Supprimer une variante la retire de ces lots.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => ':count lots retarifés.', + ], +]; diff --git a/packages/bundles/resources/lang/hr/bundles.php b/packages/bundles/resources/lang/hr/bundles.php new file mode 100644 index 0000000000..92ef01eb22 --- /dev/null +++ b/packages/bundles/resources/lang/hr/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'Odabir paketa nije ispravno oblikovan.', + 'unknown_group' => 'Paket nema grupu opcija ":id".', + 'unknown_component' => 'Opcija ":id" nije dostupna u ":group".', + 'duplicate_component' => 'Opcija u ":group" odabrana je više puta.', + 'count' => 'Odaberite između :min i :max opcija u ":group".', + 'unavailable' => 'Komponenta paketa ":identifier" nije dostupna u ovoj količini.', + ], + 'nesting' => [ + 'is_component' => 'Varijanta koja je dio drugog paketa ne može sama biti paket.', + 'is_bundle' => 'Paket ne može sadržavati drugi paket.', + 'self' => 'Paket ne može sadržavati vlastitu varijantu.', + ], + 'definition' => [ + 'empty' => 'Paket treba barem jednu komponentu.', + 'too_many_components' => 'Paket ne može imati više od :max komponenti.', + 'unknown_group' => 'Grupa opcija ne pripada ovom paketu.', + 'group_selections' => 'Ograničenja odabira za ":group" moraju zadovoljiti minimum <= maksimum <= broj opcija.', + ], + 'pricing' => [ + 'missing_component_price' => 'Komponenta ":identifier" nema cijenu u :currency, pa se paket ne može odrediti u toj valuti.', + ], + 'panel' => [ + 'column_bundle' => 'Paket', + 'badge_bundle' => 'Paket', + 'filter_label' => 'Paketi', + 'filter_only' => 'Samo paketi', + 'not_defined' => 'Ova varijanta se ne prodaje kao paket.', + 'card_title' => 'Paket', + 'card_description' => 'Prodajte ovu varijantu kao skup drugih varijanti. Zaliha se izvodi iz komponenti, a svaka komponenta se priprema i isporučuje iz narudžbe.', + 'sell_as_bundle' => 'Prodaj kao paket', + 'confirm_remove_title' => 'Prestati prodavati kao paket?', + 'confirm_remove' => 'Popis komponenti i grupe opcija bit će uklonjeni. Varijanta zadržava svoje cijene i ponovno postaje obična varijanta.', + 'confirm_components_title' => 'Cijena iz komponenata?', + 'confirm_components' => 'Vlastite osnovne cijene varijante zamjenjuju se zbrojem njezinih komponenata i ponovno se zapisuju kad god se promijeni cijena komponente. Vratite se na fiksnu cijenu da biste ih ponovno postavili ručno.', + 'pricing' => 'Cijene', + 'pricing_fixed' => 'Fiksna cijena', + 'pricing_components' => 'Zbroj komponenti', + 'discount_percentage' => 'Popust', + 'discount_hint' => 'Oduzima se od ukupnog iznosa komponenti.', + 'derived_note' => 'U ovom načinu cijene se izvode iz komponenti i prepisuju pri svakom ponovnom izračunu paketa. Prijeđite na fiksnu cijenu da biste ih postavili ručno.', + 'components' => 'Komponente', + 'components_description' => 'Uvijek uključene, ovim redoslijedom.', + 'components_empty' => 'Još nema komponenti. Dodajte barem jednu kako bi se paket mogao prodavati.', + 'add_component' => 'Dodaj komponentu', + 'quantity' => 'Kol.', + 'move_up' => 'Pomakni gore', + 'move_down' => 'Pomakni dolje', + 'remove' => 'Ukloni', + 'availability' => 'Dostupnost', + 'availability_count' => 'Iz zalihe komponenti može se prodati {count}.', + 'availability_unlimited' => 'Nije ograničeno zalihom komponenti.', + 'availability_none' => 'Nema na zalihi: jedna komponenta nije dostupna.', + 'derived_prices' => 'Izvedene cijene', + 'price' => 'Cijena', + 'list_price' => 'Prije', + 'missing_price' => 'Nema cijene za: {components}', + 'groups' => 'Grupe opcija', + 'groups_description' => 'Dopustite kupcu da bira iz skupa komponenti. Paket bez grupa je fiksan.', + 'add_group' => 'Dodaj grupu', + 'group_name' => 'Naziv grupe', + 'group_min' => 'Min.', + 'group_max' => 'Maks.', + 'group_default' => 'Zadano', + 'group_empty' => 'U ovoj grupi još nema opcija.', + 'add_option' => 'Dodaj opciju', + 'remove_group' => 'Ukloni grupu', + 'confirm_remove_group' => 'Ukloniti ovu grupu i njezine opcije?', + 'new_group_name' => 'Nova grupa', + 'saved' => 'Paket je spremljen.', + 'removed' => 'Paket je uklonjen.', + 'load_failed' => 'Paket nije moguće učitati.', + 'variant_summary_description' => 'Paketi se definiraju po varijanti. Otvorite varijantu da biste uredili njezine komponente.', + 'variant_component_count' => '{count} komponenta | {count} komponente | {count} komponenti', + 'variant_not_bundle' => 'Nije paket', + 'edit_variant' => 'Uredi varijantu', + 'included_in_title' => 'Uključeno u pakete', + 'included_in_description' => 'Brisanje varijante uklanja je iz ovih paketa.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => 'Ponovno izračunate cijene za :count paketa.', + ], +]; diff --git a/packages/bundles/resources/lang/hu/bundles.php b/packages/bundles/resources/lang/hu/bundles.php new file mode 100644 index 0000000000..e9565aac48 --- /dev/null +++ b/packages/bundles/resources/lang/hu/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'A csomag kiválasztása hibás formátumú.', + 'unknown_group' => 'A csomagnak nincs ":id" opciócsoportja.', + 'unknown_component' => 'A(z) ":id" opció nem érhető el a(z) ":group" csoportban.', + 'duplicate_component' => 'A(z) ":group" csoport egyik opcióját többször választották ki.', + 'count' => 'Válasszon :min és :max közötti számú opciót a(z) ":group" csoportban.', + 'unavailable' => 'A(z) ":identifier" csomagösszetevő nem érhető el ebben a mennyiségben.', + ], + 'nesting' => [ + 'is_component' => 'Egy másik csomag részét képező változat maga nem lehet csomag.', + 'is_bundle' => 'Egy csomag nem tartalmazhat másik csomagot.', + 'self' => 'Egy csomag nem tartalmazhatja a saját változatát.', + ], + 'definition' => [ + 'empty' => 'A csomagnak legalább egy összetevőre van szüksége.', + 'too_many_components' => 'Egy csomag legfeljebb :max összetevőt tartalmazhat.', + 'unknown_group' => 'Az opciócsoport nem tartozik ehhez a csomaghoz.', + 'group_selections' => 'A(z) ":group" kiválasztási korlátainak teljesíteniük kell: minimum <= maximum <= opciók száma.', + ], + 'pricing' => [ + 'missing_component_price' => 'A(z) ":identifier" összetevőnek nincs ára :currency pénznemben, így a csomag nem árazható be ebben a pénznemben.', + ], + 'panel' => [ + 'column_bundle' => 'Csomag', + 'badge_bundle' => 'Csomag', + 'filter_label' => 'Csomagok', + 'filter_only' => 'Csak csomagok', + 'not_defined' => 'Ez a változat nem csomagként kerül értékesítésre.', + 'card_title' => 'Csomag', + 'card_description' => 'Értékesítse ezt a változatot más változatok együtteseként. A készlet az összetevőkből származik, és minden összetevőt a rendelésből szednek össze és teljesítenek.', + 'sell_as_bundle' => 'Értékesítés csomagként', + 'confirm_remove_title' => 'Ne legyen többé csomagként értékesítve?', + 'confirm_remove' => 'Az összetevők listája és az opciócsoportok törlődnek. A változat megtartja az árait, és ismét hagyományos változattá válik.', + 'confirm_components_title' => 'Ár az összetevőkből?', + 'confirm_components' => 'A változat saját alapárait az összetevők összege váltja fel, és minden összetevő-árváltozáskor újraíródnak. Váltson vissza rögzített árra, hogy újra kézzel adja meg őket.', + 'pricing' => 'Árazás', + 'pricing_fixed' => 'Fix ár', + 'pricing_components' => 'Összetevők összege', + 'discount_percentage' => 'Kedvezmény', + 'discount_hint' => 'Az összetevők összegéből kerül levonásra.', + 'derived_note' => 'Ebben a módban az árak az összetevőkből származnak, és a csomag minden újraárazásakor felülíródnak. Váltson fix árra, ha kézzel szeretné beállítani őket.', + 'components' => 'Összetevők', + 'components_description' => 'Mindig benne vannak, ebben a sorrendben.', + 'components_empty' => 'Még nincsenek összetevők. Adjon hozzá legalább egyet, hogy a csomag értékesíthető legyen.', + 'add_component' => 'Összetevő hozzáadása', + 'quantity' => 'Menny.', + 'move_up' => 'Mozgatás felfelé', + 'move_down' => 'Mozgatás lefelé', + 'remove' => 'Eltávolítás', + 'availability' => 'Elérhetőség', + 'availability_count' => 'Az összetevők készletéből {count} adható el.', + 'availability_unlimited' => 'Az összetevők készlete nem korlátozza.', + 'availability_none' => 'Nincs készleten: egy összetevő nem elérhető.', + 'derived_prices' => 'Származtatott árak', + 'price' => 'Ár', + 'list_price' => 'Korábban', + 'missing_price' => 'Nincs ár ehhez: {components}', + 'groups' => 'Opciócsoportok', + 'groups_description' => 'Engedje, hogy a vásárló összetevők közül válasszon. A csoportok nélküli csomag rögzített.', + 'add_group' => 'Csoport hozzáadása', + 'group_name' => 'Csoport neve', + 'group_min' => 'Min.', + 'group_max' => 'Max.', + 'group_default' => 'Alapértelmezett', + 'group_empty' => 'Ebben a csoportban még nincsenek opciók.', + 'add_option' => 'Opció hozzáadása', + 'remove_group' => 'Csoport eltávolítása', + 'confirm_remove_group' => 'Eltávolítja ezt a csoportot és az opcióit?', + 'new_group_name' => 'Új csoport', + 'saved' => 'Csomag mentve.', + 'removed' => 'Csomag eltávolítva.', + 'load_failed' => 'A csomagot nem sikerült betölteni.', + 'variant_summary_description' => 'A csomagok változatonként vannak meghatározva. Nyisson meg egy változatot az összetevői szerkesztéséhez.', + 'variant_component_count' => '{count} összetevő | {count} összetevő', + 'variant_not_bundle' => 'Nem csomag', + 'edit_variant' => 'Változat szerkesztése', + 'included_in_title' => 'Csomagok része', + 'included_in_description' => 'Egy változat törlése eltávolítja azt ezekből a csomagokból.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => ':count csomag újraárazva.', + ], +]; diff --git a/packages/bundles/resources/lang/mn/bundles.php b/packages/bundles/resources/lang/mn/bundles.php new file mode 100644 index 0000000000..8553685db0 --- /dev/null +++ b/packages/bundles/resources/lang/mn/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'Багцын сонголт буруу байна.', + 'unknown_group' => 'Багцад ":id" гэсэн сонголтын бүлэг байхгүй.', + 'unknown_component' => '":id" сонголт ":group" бүлэгт байхгүй.', + 'duplicate_component' => '":group" бүлгийн нэг сонголтыг нэгээс олон удаа сонгосон байна.', + 'count' => '":group" бүлгээс :min-:max сонголт сонгоно уу.', + 'unavailable' => 'Багцын бүрэлдэхүүн ":identifier" энэ тоо хэмжээгээр боломжгүй байна.', + ], + 'nesting' => [ + 'is_component' => 'Өөр багцын бүрэлдэхүүн болсон хувилбар өөрөө багц байж болохгүй.', + 'is_bundle' => 'Багц өөр багцыг агуулж болохгүй.', + 'self' => 'Багц өөрийн хувилбарыг агуулж болохгүй.', + ], + 'definition' => [ + 'empty' => 'Багцад дор хаяж нэг бүрэлдэхүүн шаардлагатай.', + 'too_many_components' => 'Багц :max-аас олон бүрэлдэхүүнтэй байж болохгүй.', + 'unknown_group' => 'Сонголтын бүлэг энэ багцад хамаарахгүй.', + 'group_selections' => '":group" бүлгийн сонголтын хязгаар нь хамгийн бага <= хамгийн их <= сонголтын тоо гэсэн нөхцлийг хангах ёстой.', + ], + 'pricing' => [ + 'missing_component_price' => '":identifier" бүрэлдэхүүн :currency валютаар үнэгүй тул багцыг энэ валютаар үнэлэх боломжгүй.', + ], + 'panel' => [ + 'column_bundle' => 'Багц', + 'badge_bundle' => 'Багц', + 'filter_label' => 'Багцууд', + 'filter_only' => 'Зөвхөн багцууд', + 'not_defined' => 'Энэ хувилбар багц хэлбэрээр зарагддаггүй.', + 'card_title' => 'Багц', + 'card_description' => 'Энэ хувилбарыг бусад хувилбаруудын иж бүрдэл болгон зарна. Нөөц нь бүрэлдэхүүнүүдээс тооцоологдож, бүрэлдэхүүн бүр захиалгаас бэлтгэгдэн гүйцэтгэгдэнэ.', + 'sell_as_bundle' => 'Багц болгон зарах', + 'confirm_remove_title' => 'Багц болгон зарахаа зогсоох уу?', + 'confirm_remove' => 'Бүрэлдэхүүний жагсаалт болон сонголтын бүлгүүд устгагдана. Хувилбар үнээ хадгалж, энгийн хувилбар болно.', + 'confirm_components_title' => 'Бүрэлдэхүүнээс үнэ тооцох уу?', + 'confirm_components' => 'Хувилбарын өөрийн үндсэн үнийг бүрэлдэхүүн хэсгүүдийн нийлбэрээр солино, бүрэлдэхүүний үнэ өөрчлөгдөх бүрт дахин бичнэ. Гараар тохируулахын тулд тогтмол үнэ рүү буцна уу.', + 'pricing' => 'Үнэ тогтоолт', + 'pricing_fixed' => 'Тогтмол үнэ', + 'pricing_components' => 'Бүрэлдэхүүнүүдийн нийлбэр', + 'discount_percentage' => 'Хөнгөлөлт', + 'discount_hint' => 'Бүрэлдэхүүний нийт дүнгээс хасагдана.', + 'derived_note' => 'Энэ горимд үнэ нь бүрэлдэхүүнүүдээс тооцоологдож, багцын үнийг дахин тооцох бүрт дарж бичигдэнэ. Гараар тохируулахын тулд тогтмол үнэ рүү шилжинэ үү.', + 'components' => 'Бүрэлдэхүүнүүд', + 'components_description' => 'Энэ дарааллаар үргэлж багтана.', + 'components_empty' => 'Бүрэлдэхүүн байхгүй байна. Багцыг зарах боломжтой болгохын тулд дор хаяж нэгийг нэмнэ үү.', + 'add_component' => 'Бүрэлдэхүүн нэмэх', + 'quantity' => 'Тоо', + 'move_up' => 'Дээш зөөх', + 'move_down' => 'Доош зөөх', + 'remove' => 'Хасах', + 'availability' => 'Боломжит нөөц', + 'availability_count' => 'Бүрэлдэхүүний нөөцөөс {count} ширхэг зарах боломжтой.', + 'availability_unlimited' => 'Бүрэлдэхүүний нөөцөөр хязгаарлагдахгүй.', + 'availability_none' => 'Нөөц дууссан: нэг бүрэлдэхүүн байхгүй байна.', + 'derived_prices' => 'Тооцоолсон үнэ', + 'price' => 'Үнэ', + 'list_price' => 'Өмнөх үнэ', + 'missing_price' => 'Үнэ байхгүй: {components}', + 'groups' => 'Сонголтын бүлгүүд', + 'groups_description' => 'Худалдан авагчид бүрэлдэхүүнүүдээс сонгох боломж олгоно. Бүлэггүй багц тогтмол байна.', + 'add_group' => 'Бүлэг нэмэх', + 'group_name' => 'Бүлгийн нэр', + 'group_min' => 'Хамгийн бага', + 'group_max' => 'Хамгийн их', + 'group_default' => 'Үндсэн', + 'group_empty' => 'Энэ бүлэгт сонголт байхгүй байна.', + 'add_option' => 'Сонголт нэмэх', + 'remove_group' => 'Бүлэг хасах', + 'confirm_remove_group' => 'Энэ бүлэг болон сонголтуудыг нь хасах уу?', + 'new_group_name' => 'Шинэ бүлэг', + 'saved' => 'Багц хадгалагдлаа.', + 'removed' => 'Багц хасагдлаа.', + 'load_failed' => 'Багцыг ачаалж чадсангүй.', + 'variant_summary_description' => 'Багцыг хувилбар бүрээр тодорхойлно. Бүрэлдэхүүнийг засахын тулд хувилбарыг нээнэ үү.', + 'variant_component_count' => '{count} бүрэлдэхүүн | {count} бүрэлдэхүүн', + 'variant_not_bundle' => 'Багц биш', + 'edit_variant' => 'Хувилбар засах', + 'included_in_title' => 'Багцад багтсан', + 'included_in_description' => 'Хувилбарыг устгавал эдгээр багцаас хасагдана.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => ':count багцын үнийг дахин тооцооллоо.', + ], +]; diff --git a/packages/bundles/resources/lang/nl/bundles.php b/packages/bundles/resources/lang/nl/bundles.php new file mode 100644 index 0000000000..7befcea261 --- /dev/null +++ b/packages/bundles/resources/lang/nl/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'De bundelselectie is ongeldig opgebouwd.', + 'unknown_group' => 'De bundel heeft geen optiegroep ":id".', + 'unknown_component' => 'Optie ":id" is niet beschikbaar in ":group".', + 'duplicate_component' => 'Een optie in ":group" is meer dan één keer gekozen.', + 'count' => 'Kies tussen :min en :max opties in ":group".', + 'unavailable' => 'Bundelonderdeel ":identifier" is niet beschikbaar in dit aantal.', + ], + 'nesting' => [ + 'is_component' => 'Een variant die deel uitmaakt van een andere bundel kan zelf geen bundel zijn.', + 'is_bundle' => 'Een bundel kan geen andere bundel bevatten.', + 'self' => 'Een bundel kan zijn eigen variant niet bevatten.', + ], + 'definition' => [ + 'empty' => 'Een bundel heeft minstens één onderdeel nodig.', + 'too_many_components' => 'Een bundel mag niet meer dan :max onderdelen hebben.', + 'unknown_group' => 'De optiegroep hoort niet bij deze bundel.', + 'group_selections' => 'De selectielimieten van ":group" moeten voldoen aan minimum <= maximum <= aantal opties.', + ], + 'pricing' => [ + 'missing_component_price' => 'Onderdeel ":identifier" heeft geen prijs in :currency, dus de bundel kan in die valuta niet geprijsd worden.', + ], + 'panel' => [ + 'column_bundle' => 'Bundel', + 'badge_bundle' => 'Bundel', + 'filter_label' => 'Bundels', + 'filter_only' => 'Alleen bundels', + 'not_defined' => 'Deze variant wordt niet als bundel verkocht.', + 'card_title' => 'Bundel', + 'card_description' => 'Verkoop deze variant als een set van andere varianten. De voorraad wordt afgeleid van de onderdelen en elk onderdeel wordt vanuit de bestelling gepickt en afgehandeld.', + 'sell_as_bundle' => 'Als bundel verkopen', + 'confirm_remove_title' => 'Niet langer als bundel verkopen?', + 'confirm_remove' => 'De onderdelenlijst en optiegroepen worden verwijderd. De variant behoudt zijn prijzen en wordt weer een gewone variant.', + 'confirm_components_title' => 'Prijs uit de onderdelen berekenen?', + 'confirm_components' => 'De eigen basisprijzen van de variant worden vervangen door de som van de onderdelen en opnieuw geschreven zodra de prijs van een onderdeel wijzigt. Schakel terug naar een vaste prijs om ze weer handmatig in te stellen.', + 'pricing' => 'Prijsbepaling', + 'pricing_fixed' => 'Vaste prijs', + 'pricing_components' => 'Som van de onderdelen', + 'discount_percentage' => 'Korting', + 'discount_hint' => 'Wordt van het onderdelentotaal afgetrokken.', + 'derived_note' => 'Prijzen in deze modus worden afgeleid van de onderdelen en overschreven bij elke herberekening. Schakel over naar een vaste prijs om ze handmatig in te stellen.', + 'components' => 'Onderdelen', + 'components_description' => 'Altijd inbegrepen, in deze volgorde.', + 'components_empty' => 'Nog geen onderdelen. Voeg er minstens één toe om de bundel verkoopbaar te maken.', + 'add_component' => 'Onderdeel toevoegen', + 'quantity' => 'Aantal', + 'move_up' => 'Omhoog', + 'move_down' => 'Omlaag', + 'remove' => 'Verwijderen', + 'availability' => 'Beschikbaarheid', + 'availability_count' => '{count} kunnen worden verkocht uit de onderdelenvoorraad.', + 'availability_unlimited' => 'Niet beperkt door de onderdelenvoorraad.', + 'availability_none' => 'Niet op voorraad: een onderdeel is niet beschikbaar.', + 'derived_prices' => 'Afgeleide prijzen', + 'price' => 'Prijs', + 'list_price' => 'Was', + 'missing_price' => 'Geen prijs voor: {components}', + 'groups' => 'Optiegroepen', + 'groups_description' => 'Laat de klant kiezen uit een set onderdelen. Een bundel zonder groepen is vast.', + 'add_group' => 'Groep toevoegen', + 'group_name' => 'Groepsnaam', + 'group_min' => 'Min.', + 'group_max' => 'Max.', + 'group_default' => 'Standaard', + 'group_empty' => 'Nog geen opties in deze groep.', + 'add_option' => 'Optie toevoegen', + 'remove_group' => 'Groep verwijderen', + 'confirm_remove_group' => 'Deze groep en zijn opties verwijderen?', + 'new_group_name' => 'Nieuwe groep', + 'saved' => 'Bundel opgeslagen.', + 'removed' => 'Bundel verwijderd.', + 'load_failed' => 'De bundel kon niet worden geladen.', + 'variant_summary_description' => 'Bundels worden per variant gedefinieerd. Open een variant om de onderdelen te bewerken.', + 'variant_component_count' => '{count} onderdeel | {count} onderdelen', + 'variant_not_bundle' => 'Geen bundel', + 'edit_variant' => 'Variant bewerken', + 'included_in_title' => 'Opgenomen in bundels', + 'included_in_description' => 'Als je een variant verwijdert, wordt deze uit deze bundels gehaald.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => ':count bundels opnieuw geprijsd.', + ], +]; diff --git a/packages/bundles/resources/lang/pl/bundles.php b/packages/bundles/resources/lang/pl/bundles.php new file mode 100644 index 0000000000..8943d49a79 --- /dev/null +++ b/packages/bundles/resources/lang/pl/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'Wybór zestawu jest nieprawidłowy.', + 'unknown_group' => 'Zestaw nie ma grupy opcji ":id".', + 'unknown_component' => 'Opcja ":id" nie jest dostępna w ":group".', + 'duplicate_component' => 'Opcja w ":group" została wybrana więcej niż raz.', + 'count' => 'Wybierz od :min do :max opcji w ":group".', + 'unavailable' => 'Składnik zestawu ":identifier" nie jest dostępny w tej ilości.', + ], + 'nesting' => [ + 'is_component' => 'Wariant będący częścią innego zestawu nie może sam być zestawem.', + 'is_bundle' => 'Zestaw nie może zawierać innego zestawu.', + 'self' => 'Zestaw nie może zawierać własnego wariantu.', + ], + 'definition' => [ + 'empty' => 'Zestaw wymaga co najmniej jednego składnika.', + 'too_many_components' => 'Zestaw nie może mieć więcej niż :max składników.', + 'unknown_group' => 'Grupa opcji nie należy do tego zestawu.', + 'group_selections' => 'Limity wyboru dla ":group" muszą spełniać warunek minimum <= maksimum <= liczba opcji.', + ], + 'pricing' => [ + 'missing_component_price' => 'Składnik ":identifier" nie ma ceny w :currency, więc zestaw nie może zostać wyceniony w tej walucie.', + ], + 'panel' => [ + 'column_bundle' => 'Zestaw', + 'badge_bundle' => 'Zestaw', + 'filter_label' => 'Zestawy', + 'filter_only' => 'Tylko zestawy', + 'not_defined' => 'Ten wariant nie jest sprzedawany jako zestaw.', + 'card_title' => 'Zestaw', + 'card_description' => 'Sprzedawaj ten wariant jako komplet innych wariantów. Stan magazynowy wynika ze składników, a każdy składnik jest kompletowany i realizowany z zamówienia.', + 'sell_as_bundle' => 'Sprzedawaj jako zestaw', + 'confirm_remove_title' => 'Przestać sprzedawać jako zestaw?', + 'confirm_remove' => 'Lista składników i grupy opcji zostaną usunięte. Wariant zachowa swoje ceny i znów będzie zwykłym wariantem.', + 'confirm_components_title' => 'Wyliczać cenę ze składników?', + 'confirm_components' => 'Własne ceny bazowe wariantu zostaną zastąpione sumą jego składników i nadpisane przy każdej zmianie ceny składnika. Wróć do ceny stałej, aby znów ustawiać je ręcznie.', + 'pricing' => 'Wycena', + 'pricing_fixed' => 'Cena stała', + 'pricing_components' => 'Suma składników', + 'discount_percentage' => 'Rabat', + 'discount_hint' => 'Odejmowany od sumy składników.', + 'derived_note' => 'W tym trybie ceny wynikają ze składników i są nadpisywane przy każdym przeliczeniu zestawu. Przełącz na cenę stałą, aby ustawić je ręcznie.', + 'components' => 'Składniki', + 'components_description' => 'Zawsze w zestawie, w tej kolejności.', + 'components_empty' => 'Brak składników. Dodaj co najmniej jeden, aby zestaw można było sprzedawać.', + 'add_component' => 'Dodaj składnik', + 'quantity' => 'Ilość', + 'move_up' => 'Przenieś wyżej', + 'move_down' => 'Przenieś niżej', + 'remove' => 'Usuń', + 'availability' => 'Dostępność', + 'availability_count' => 'Ze stanu składników można sprzedać {count}.', + 'availability_unlimited' => 'Bez ograniczenia stanem składników.', + 'availability_none' => 'Brak na stanie: jeden ze składników jest niedostępny.', + 'derived_prices' => 'Ceny wynikowe', + 'price' => 'Cena', + 'list_price' => 'Poprzednio', + 'missing_price' => 'Brak ceny dla: {components}', + 'groups' => 'Grupy opcji', + 'groups_description' => 'Pozwól klientowi wybrać spośród zestawu składników. Zestaw bez grup jest stały.', + 'add_group' => 'Dodaj grupę', + 'group_name' => 'Nazwa grupy', + 'group_min' => 'Min.', + 'group_max' => 'Maks.', + 'group_default' => 'Domyślny', + 'group_empty' => 'W tej grupie nie ma jeszcze opcji.', + 'add_option' => 'Dodaj opcję', + 'remove_group' => 'Usuń grupę', + 'confirm_remove_group' => 'Usunąć tę grupę i jej opcje?', + 'new_group_name' => 'Nowa grupa', + 'saved' => 'Zestaw zapisany.', + 'removed' => 'Zestaw usunięty.', + 'load_failed' => 'Nie udało się wczytać zestawu.', + 'variant_summary_description' => 'Zestawy definiuje się dla wariantu. Otwórz wariant, aby edytować jego składniki.', + 'variant_component_count' => '{count} składnik | {count} składniki | {count} składników', + 'variant_not_bundle' => 'To nie zestaw', + 'edit_variant' => 'Edytuj wariant', + 'included_in_title' => 'Wchodzi w skład zestawów', + 'included_in_description' => 'Usunięcie wariantu usuwa go z tych zestawów.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => 'Przeliczono ceny :count zestawów.', + ], +]; diff --git a/packages/bundles/resources/lang/pt_BR/bundles.php b/packages/bundles/resources/lang/pt_BR/bundles.php new file mode 100644 index 0000000000..9b48aee3c7 --- /dev/null +++ b/packages/bundles/resources/lang/pt_BR/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'A seleção do pacote está malformada.', + 'unknown_group' => 'O pacote não possui o grupo de opções ":id".', + 'unknown_component' => 'A opção ":id" não está disponível em ":group".', + 'duplicate_component' => 'Uma opção em ":group" foi escolhida mais de uma vez.', + 'count' => 'Escolha entre :min e :max opções em ":group".', + 'unavailable' => 'O componente do pacote ":identifier" não está disponível nesta quantidade.', + ], + 'nesting' => [ + 'is_component' => 'Uma variante que faz parte de outro pacote não pode ser um pacote.', + 'is_bundle' => 'Um pacote não pode conter outro pacote.', + 'self' => 'Um pacote não pode conter sua própria variante.', + ], + 'definition' => [ + 'empty' => 'Um pacote precisa de pelo menos um componente.', + 'too_many_components' => 'Um pacote não pode ter mais de :max componentes.', + 'unknown_group' => 'O grupo de opções não pertence a este pacote.', + 'group_selections' => 'Os limites de seleção de ":group" devem respeitar mínimo <= máximo <= número de opções.', + ], + 'pricing' => [ + 'missing_component_price' => 'O componente ":identifier" não tem preço em :currency, portanto o pacote não pode ser precificado nessa moeda.', + ], + 'panel' => [ + 'column_bundle' => 'Pacote', + 'badge_bundle' => 'Pacote', + 'filter_label' => 'Pacotes', + 'filter_only' => 'Somente pacotes', + 'not_defined' => 'Esta variante não é vendida como pacote.', + 'card_title' => 'Pacote', + 'card_description' => 'Venda esta variante como um conjunto de outras variantes. O estoque é derivado dos componentes e cada componente é separado e atendido a partir do pedido.', + 'sell_as_bundle' => 'Vender como pacote', + 'confirm_remove_title' => 'Parar de vender como pacote?', + 'confirm_remove' => 'A lista de componentes e os grupos de opções são removidos. A variante mantém seus preços e volta a ser uma variante comum.', + 'confirm_components_title' => 'Calcular o preço a partir dos componentes?', + 'confirm_components' => 'Os preços base da própria variante são substituídos pela soma dos componentes e reescritos sempre que o preço de um componente mudar. Volte para preço fixo para defini-los manualmente de novo.', + 'pricing' => 'Precificação', + 'pricing_fixed' => 'Preço fixo', + 'pricing_components' => 'Soma dos componentes', + 'discount_percentage' => 'Desconto', + 'discount_hint' => 'Descontado do total dos componentes.', + 'derived_note' => 'Neste modo os preços são derivados dos componentes e sobrescritos sempre que o pacote é reprecificado. Mude para preço fixo para defini-los manualmente.', + 'components' => 'Componentes', + 'components_description' => 'Sempre incluídos, nesta ordem.', + 'components_empty' => 'Nenhum componente ainda. Adicione pelo menos um para que o pacote possa ser vendido.', + 'add_component' => 'Adicionar componente', + 'quantity' => 'Qtd.', + 'move_up' => 'Mover para cima', + 'move_down' => 'Mover para baixo', + 'remove' => 'Remover', + 'availability' => 'Disponibilidade', + 'availability_count' => '{count} podem ser vendidos com o estoque dos componentes.', + 'availability_unlimited' => 'Não limitado pelo estoque dos componentes.', + 'availability_none' => 'Esgotado: um componente está indisponível.', + 'derived_prices' => 'Preços derivados', + 'price' => 'Preço', + 'list_price' => 'De', + 'missing_price' => 'Sem preço para: {components}', + 'groups' => 'Grupos de opções', + 'groups_description' => 'Deixe o cliente escolher entre um conjunto de componentes. Um pacote sem grupos é fixo.', + 'add_group' => 'Adicionar grupo', + 'group_name' => 'Nome do grupo', + 'group_min' => 'Mín.', + 'group_max' => 'Máx.', + 'group_default' => 'Padrão', + 'group_empty' => 'Nenhuma opção neste grupo ainda.', + 'add_option' => 'Adicionar opção', + 'remove_group' => 'Remover grupo', + 'confirm_remove_group' => 'Remover este grupo e suas opções?', + 'new_group_name' => 'Novo grupo', + 'saved' => 'Pacote salvo.', + 'removed' => 'Pacote removido.', + 'load_failed' => 'Não foi possível carregar o pacote.', + 'variant_summary_description' => 'Pacotes são definidos por variante. Abra uma variante para editar seus componentes.', + 'variant_component_count' => '{count} componente | {count} componentes', + 'variant_not_bundle' => 'Não é um pacote', + 'edit_variant' => 'Editar variante', + 'included_in_title' => 'Incluído em pacotes', + 'included_in_description' => 'Excluir uma variante a remove destes pacotes.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => ':count pacotes reprecificados.', + ], +]; diff --git a/packages/bundles/resources/lang/ro/bundles.php b/packages/bundles/resources/lang/ro/bundles.php new file mode 100644 index 0000000000..1e776d8f11 --- /dev/null +++ b/packages/bundles/resources/lang/ro/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'Selecția pachetului este invalidă.', + 'unknown_group' => 'Pachetul nu are grupul de opțiuni ":id".', + 'unknown_component' => 'Opțiunea ":id" nu este disponibilă în ":group".', + 'duplicate_component' => 'O opțiune din ":group" a fost aleasă de mai multe ori.', + 'count' => 'Alegeți între :min și :max opțiuni în ":group".', + 'unavailable' => 'Componenta pachetului ":identifier" nu este disponibilă în această cantitate.', + ], + 'nesting' => [ + 'is_component' => 'O variantă care face parte din alt pachet nu poate fi la rândul ei un pachet.', + 'is_bundle' => 'Un pachet nu poate conține un alt pachet.', + 'self' => 'Un pachet nu poate conține propria variantă.', + ], + 'definition' => [ + 'empty' => 'Un pachet are nevoie de cel puțin o componentă.', + 'too_many_components' => 'Un pachet nu poate avea mai mult de :max componente.', + 'unknown_group' => 'Grupul de opțiuni nu aparține acestui pachet.', + 'group_selections' => 'Limitele de selecție pentru ":group" trebuie să respecte minim <= maxim <= numărul de opțiuni.', + ], + 'pricing' => [ + 'missing_component_price' => 'Componenta ":identifier" nu are preț în :currency, așa că pachetul nu poate fi evaluat în această monedă.', + ], + 'panel' => [ + 'column_bundle' => 'Pachet', + 'badge_bundle' => 'Pachet', + 'filter_label' => 'Pachete', + 'filter_only' => 'Doar pachete', + 'not_defined' => 'Această variantă nu este vândută ca pachet.', + 'card_title' => 'Pachet', + 'card_description' => 'Vinde această variantă ca un set de alte variante. Stocul este derivat din componente, iar fiecare componentă este pregătită și livrată din comandă.', + 'sell_as_bundle' => 'Vinde ca pachet', + 'confirm_remove_title' => 'Nu mai vinzi ca pachet?', + 'confirm_remove' => 'Lista de componente și grupurile de opțiuni sunt eliminate. Varianta își păstrează prețurile și redevine o variantă obișnuită.', + 'confirm_components_title' => 'Preț calculat din componente?', + 'confirm_components' => 'Prețurile de bază proprii ale variantei sunt înlocuite cu suma componentelor și rescrise ori de câte ori se schimbă prețul unei componente. Reveniți la preț fix pentru a le seta din nou manual.', + 'pricing' => 'Prețuri', + 'pricing_fixed' => 'Preț fix', + 'pricing_components' => 'Suma componentelor', + 'discount_percentage' => 'Reducere', + 'discount_hint' => 'Scăzută din totalul componentelor.', + 'derived_note' => 'În acest mod prețurile sunt derivate din componente și suprascrise la fiecare recalculare a pachetului. Treci la preț fix pentru a le seta manual.', + 'components' => 'Componente', + 'components_description' => 'Întotdeauna incluse, în această ordine.', + 'components_empty' => 'Nicio componentă încă. Adaugă cel puțin una pentru ca pachetul să poată fi vândut.', + 'add_component' => 'Adaugă componentă', + 'quantity' => 'Cant.', + 'move_up' => 'Mută în sus', + 'move_down' => 'Mută în jos', + 'remove' => 'Elimină', + 'availability' => 'Disponibilitate', + 'availability_count' => '{count} pot fi vândute din stocul componentelor.', + 'availability_unlimited' => 'Nelimitat de stocul componentelor.', + 'availability_none' => 'Stoc epuizat: o componentă nu este disponibilă.', + 'derived_prices' => 'Prețuri derivate', + 'price' => 'Preț', + 'list_price' => 'Înainte', + 'missing_price' => 'Fără preț pentru: {components}', + 'groups' => 'Grupuri de opțiuni', + 'groups_description' => 'Lasă clientul să aleagă dintr-un set de componente. Un pachet fără grupuri este fix.', + 'add_group' => 'Adaugă grup', + 'group_name' => 'Numele grupului', + 'group_min' => 'Min.', + 'group_max' => 'Max.', + 'group_default' => 'Implicit', + 'group_empty' => 'Nicio opțiune în acest grup încă.', + 'add_option' => 'Adaugă opțiune', + 'remove_group' => 'Elimină grupul', + 'confirm_remove_group' => 'Elimini acest grup și opțiunile sale?', + 'new_group_name' => 'Grup nou', + 'saved' => 'Pachet salvat.', + 'removed' => 'Pachet eliminat.', + 'load_failed' => 'Pachetul nu a putut fi încărcat.', + 'variant_summary_description' => 'Pachetele se definesc per variantă. Deschide o variantă pentru a-i edita componentele.', + 'variant_component_count' => '{count} componentă | {count} componente', + 'variant_not_bundle' => 'Nu este pachet', + 'edit_variant' => 'Editează varianta', + 'included_in_title' => 'Inclus în pachete', + 'included_in_description' => 'Ștergerea unei variante o elimină din aceste pachete.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => 'Prețurile pentru :count pachete au fost recalculate.', + ], +]; diff --git a/packages/bundles/resources/lang/tr/bundles.php b/packages/bundles/resources/lang/tr/bundles.php new file mode 100644 index 0000000000..085956b908 --- /dev/null +++ b/packages/bundles/resources/lang/tr/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'Paket seçimi hatalı biçimlendirilmiş.', + 'unknown_group' => 'Pakette ":id" adlı bir seçenek grubu yok.', + 'unknown_component' => '":id" seçeneği ":group" içinde mevcut değil.', + 'duplicate_component' => '":group" içindeki bir seçenek birden fazla kez seçildi.', + 'count' => '":group" içinde :min ile :max arasında seçenek seçin.', + 'unavailable' => 'Paket bileşeni ":identifier" bu miktarda mevcut değil.', + ], + 'nesting' => [ + 'is_component' => 'Başka bir paketin parçası olan bir varyant kendisi paket olamaz.', + 'is_bundle' => 'Bir paket başka bir paket içeremez.', + 'self' => 'Bir paket kendi varyantını içeremez.', + ], + 'definition' => [ + 'empty' => 'Bir paketin en az bir bileşeni olmalıdır.', + 'too_many_components' => 'Bir paket en fazla :max bileşen içerebilir.', + 'unknown_group' => 'Seçenek grubu bu pakete ait değil.', + 'group_selections' => '":group" için seçim sınırları minimum <= maksimum <= seçenek sayısı koşulunu sağlamalıdır.', + ], + 'pricing' => [ + 'missing_component_price' => '":identifier" bileşeninin :currency cinsinden fiyatı yok, bu nedenle paket bu para biriminde fiyatlandırılamaz.', + ], + 'panel' => [ + 'column_bundle' => 'Paket', + 'badge_bundle' => 'Paket', + 'filter_label' => 'Paketler', + 'filter_only' => 'Yalnızca paketler', + 'not_defined' => 'Bu varyant paket olarak satılmıyor.', + 'card_title' => 'Paket', + 'card_description' => 'Bu varyantı başka varyantlardan oluşan bir set olarak satın. Stok bileşenlerden türetilir ve her bileşen siparişten toplanıp teslim edilir.', + 'sell_as_bundle' => 'Paket olarak sat', + 'confirm_remove_title' => 'Paket olarak satış durdurulsun mu?', + 'confirm_remove' => 'Bileşen listesi ve seçenek grupları kaldırılır. Varyant fiyatlarını korur ve yeniden sıradan bir varyant olur.', + 'confirm_components_title' => 'Fiyat bileşenlerden hesaplansın mı?', + 'confirm_components' => 'Varyantın kendi taban fiyatları bileşenlerinin toplamıyla değiştirilir ve bir bileşenin fiyatı her değiştiğinde yeniden yazılır. Yeniden elle belirlemek için sabit fiyata dönün.', + 'pricing' => 'Fiyatlandırma', + 'pricing_fixed' => 'Sabit fiyat', + 'pricing_components' => 'Bileşenlerin toplamı', + 'discount_percentage' => 'İndirim', + 'discount_hint' => 'Bileşen toplamından düşülür.', + 'derived_note' => 'Bu modda fiyatlar bileşenlerden türetilir ve paket her yeniden fiyatlandırıldığında üzerine yazılır. Elle belirlemek için sabit fiyata geçin.', + 'components' => 'Bileşenler', + 'components_description' => 'Her zaman dahildir, bu sırayla.', + 'components_empty' => 'Henüz bileşen yok. Paketin satılabilmesi için en az bir tane ekleyin.', + 'add_component' => 'Bileşen ekle', + 'quantity' => 'Adet', + 'move_up' => 'Yukarı taşı', + 'move_down' => 'Aşağı taşı', + 'remove' => 'Kaldır', + 'availability' => 'Stok durumu', + 'availability_count' => 'Bileşen stoğundan {count} adet satılabilir.', + 'availability_unlimited' => 'Bileşen stoğuyla sınırlı değil.', + 'availability_none' => 'Stokta yok: bir bileşen mevcut değil.', + 'derived_prices' => 'Türetilen fiyatlar', + 'price' => 'Fiyat', + 'list_price' => 'Önceki', + 'missing_price' => 'Fiyatı olmayanlar: {components}', + 'groups' => 'Seçenek grupları', + 'groups_description' => 'Müşterinin bir bileşen kümesinden seçim yapmasına izin verin. Grubu olmayan bir paket sabittir.', + 'add_group' => 'Grup ekle', + 'group_name' => 'Grup adı', + 'group_min' => 'Min.', + 'group_max' => 'Maks.', + 'group_default' => 'Varsayılan', + 'group_empty' => 'Bu grupta henüz seçenek yok.', + 'add_option' => 'Seçenek ekle', + 'remove_group' => 'Grubu kaldır', + 'confirm_remove_group' => 'Bu grup ve seçenekleri kaldırılsın mı?', + 'new_group_name' => 'Yeni grup', + 'saved' => 'Paket kaydedildi.', + 'removed' => 'Paket kaldırıldı.', + 'load_failed' => 'Paket yüklenemedi.', + 'variant_summary_description' => 'Paketler varyant başına tanımlanır. Bileşenlerini düzenlemek için bir varyantı açın.', + 'variant_component_count' => '{count} bileşen | {count} bileşen', + 'variant_not_bundle' => 'Paket değil', + 'edit_variant' => 'Varyantı düzenle', + 'included_in_title' => 'Dahil olduğu paketler', + 'included_in_description' => 'Bir varyantı silmek onu bu paketlerden çıkarır.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => ':count paketin fiyatı yeniden hesaplandı.', + ], +]; diff --git a/packages/bundles/resources/lang/vi/bundles.php b/packages/bundles/resources/lang/vi/bundles.php new file mode 100644 index 0000000000..2aad83dee9 --- /dev/null +++ b/packages/bundles/resources/lang/vi/bundles.php @@ -0,0 +1,87 @@ + [ + 'malformed' => 'Lựa chọn gói sản phẩm không hợp lệ.', + 'unknown_group' => 'Gói sản phẩm không có nhóm tùy chọn ":id".', + 'unknown_component' => 'Tùy chọn ":id" không có trong ":group".', + 'duplicate_component' => 'Một tùy chọn trong ":group" đã được chọn nhiều lần.', + 'count' => 'Hãy chọn từ :min đến :max tùy chọn trong ":group".', + 'unavailable' => 'Thành phần ":identifier" của gói không có sẵn với số lượng này.', + ], + 'nesting' => [ + 'is_component' => 'Một biến thể thuộc gói khác không thể tự là một gói.', + 'is_bundle' => 'Một gói không thể chứa gói khác.', + 'self' => 'Một gói không thể chứa chính biến thể của nó.', + ], + 'definition' => [ + 'empty' => 'Một gói cần ít nhất một thành phần.', + 'too_many_components' => 'Một gói không thể có nhiều hơn :max thành phần.', + 'unknown_group' => 'Nhóm tùy chọn không thuộc gói này.', + 'group_selections' => 'Giới hạn lựa chọn của ":group" phải thỏa mãn tối thiểu <= tối đa <= số tùy chọn.', + ], + 'pricing' => [ + 'missing_component_price' => 'Thành phần ":identifier" không có giá bằng :currency, vì vậy gói không thể được định giá bằng loại tiền đó.', + ], + 'panel' => [ + 'column_bundle' => 'Gói', + 'badge_bundle' => 'Gói', + 'filter_label' => 'Gói sản phẩm', + 'filter_only' => 'Chỉ gói sản phẩm', + 'not_defined' => 'Biến thể này không được bán dưới dạng gói.', + 'card_title' => 'Gói sản phẩm', + 'card_description' => 'Bán biến thể này như một bộ gồm các biến thể khác. Tồn kho được tính từ các thành phần và mỗi thành phần được soạn và giao từ đơn hàng.', + 'sell_as_bundle' => 'Bán dưới dạng gói', + 'confirm_remove_title' => 'Ngừng bán dưới dạng gói?', + 'confirm_remove' => 'Danh sách thành phần và các nhóm tùy chọn sẽ bị xóa. Biến thể giữ nguyên giá và trở lại thành biến thể thông thường.', + 'confirm_components_title' => 'Tính giá từ các thành phần?', + 'confirm_components' => 'Giá cơ bản riêng của biến thể sẽ được thay bằng tổng các thành phần và được ghi lại mỗi khi giá một thành phần thay đổi. Chuyển về giá cố định để đặt lại thủ công.', + 'pricing' => 'Định giá', + 'pricing_fixed' => 'Giá cố định', + 'pricing_components' => 'Tổng các thành phần', + 'discount_percentage' => 'Giảm giá', + 'discount_hint' => 'Được trừ vào tổng giá các thành phần.', + 'derived_note' => 'Ở chế độ này, giá được tính từ các thành phần và bị ghi đè mỗi khi gói được tính lại giá. Chuyển sang giá cố định để đặt giá thủ công.', + 'components' => 'Thành phần', + 'components_description' => 'Luôn được bao gồm, theo thứ tự này.', + 'components_empty' => 'Chưa có thành phần nào. Thêm ít nhất một thành phần để gói có thể bán được.', + 'add_component' => 'Thêm thành phần', + 'quantity' => 'SL', + 'move_up' => 'Chuyển lên', + 'move_down' => 'Chuyển xuống', + 'remove' => 'Xóa', + 'availability' => 'Tình trạng còn hàng', + 'availability_count' => 'Có thể bán {count} từ tồn kho của các thành phần.', + 'availability_unlimited' => 'Không bị giới hạn bởi tồn kho của các thành phần.', + 'availability_none' => 'Hết hàng: một thành phần không có sẵn.', + 'derived_prices' => 'Giá được tính', + 'price' => 'Giá', + 'list_price' => 'Giá cũ', + 'missing_price' => 'Chưa có giá cho: {components}', + 'groups' => 'Nhóm tùy chọn', + 'groups_description' => 'Cho phép khách hàng chọn từ một tập hợp thành phần. Gói không có nhóm là gói cố định.', + 'add_group' => 'Thêm nhóm', + 'group_name' => 'Tên nhóm', + 'group_min' => 'Tối thiểu', + 'group_max' => 'Tối đa', + 'group_default' => 'Mặc định', + 'group_empty' => 'Nhóm này chưa có tùy chọn nào.', + 'add_option' => 'Thêm tùy chọn', + 'remove_group' => 'Xóa nhóm', + 'confirm_remove_group' => 'Xóa nhóm này và các tùy chọn của nó?', + 'new_group_name' => 'Nhóm mới', + 'saved' => 'Đã lưu gói.', + 'removed' => 'Đã xóa gói.', + 'load_failed' => 'Không thể tải gói.', + 'variant_summary_description' => 'Gói được định nghĩa cho từng biến thể. Mở một biến thể để chỉnh sửa các thành phần của nó.', + 'variant_component_count' => '{count} thành phần | {count} thành phần', + 'variant_not_bundle' => 'Không phải gói', + 'edit_variant' => 'Chỉnh sửa biến thể', + 'included_in_title' => 'Có trong các gói', + 'included_in_description' => 'Xóa một biến thể sẽ loại nó khỏi các gói này.', + 'included_quantity' => 'x{quantity}', + ], + 'console' => [ + 'repriced' => 'Đã tính lại giá cho :count gói.', + ], +]; diff --git a/packages/bundles/src/Actions/DefineBundle.php b/packages/bundles/src/Actions/DefineBundle.php new file mode 100644 index 0000000000..b02c6f9cc7 --- /dev/null +++ b/packages/bundles/src/Actions/DefineBundle.php @@ -0,0 +1,36 @@ +where('product_variant_id', $variant->getKey())->exists()) { + throw BundleNesting::isComponent(); + } + + $bundle = Bundle::query()->firstOrNew(['product_variant_id' => $variant->getKey()]); + + $bundle->fill([ + 'pricing' => $pricing, + 'discount_percentage' => $pricing === BundlePricing::Components ? $discountPercentage : null, + ])->save(); + + $bundle->setRelation('variant', $variant); + + return $this->reprice->execute($bundle); + } +} diff --git a/packages/bundles/src/Actions/DeleteBundle.php b/packages/bundles/src/Actions/DeleteBundle.php new file mode 100644 index 0000000000..2ef65044b5 --- /dev/null +++ b/packages/bundles/src/Actions/DeleteBundle.php @@ -0,0 +1,22 @@ +getConnection()->transaction(function () use ($bundle) { + // Deleted through the models rather than the FK cascade so cache + // invalidation and activity logging see every row go. + $bundle->components()->get()->each(fn (BundleComponent $component) => $component->delete()); + $bundle->groups()->get()->each(fn (BundleGroup $group) => $group->delete()); + $bundle->delete(); + }); + } +} diff --git a/packages/bundles/src/Actions/RepriceBundle.php b/packages/bundles/src/Actions/RepriceBundle.php new file mode 100644 index 0000000000..5db3238621 --- /dev/null +++ b/packages/bundles/src/Actions/RepriceBundle.php @@ -0,0 +1,149 @@ + 1`) are never touched. + */ +class RepriceBundle implements RepricesBundle +{ + public function __construct( + protected PriceCalculatorInterface $calculator, + ) {} + + public function execute(Bundle $bundle): Bundle + { + if ($bundle->pricing !== BundlePricing::Components) { + return $bundle; + } + + $bundle->loadMissing(['variant', 'components.variant.prices']); + + $components = $bundle->components + ->filter(fn (BundleComponent $component) => $component->isFixed() || $component->default) + ->values(); + + // Nothing to derive from yet; leave whatever rows the variant has alone. + if ($components->isEmpty() || ! $bundle->variant) { + return $bundle; + } + + $variant = $bundle->variant; + $customerGroups = CustomerGroup::query()->get(); + $written = []; + + foreach (Currency::query()->get() as $currency) { + $sum = $this->sum($components, $currency, null); + + if ($sum === null) { + continue; + } + + $written[] = $this->write($bundle, $variant, $currency, null, $sum); + + foreach ($customerGroups as $customerGroup) { + if (! $this->anyGroupPrice($components, $currency, $customerGroup)) { + continue; + } + + $written[] = $this->write($bundle, $variant, $currency, $customerGroup, (int) $this->sum($components, $currency, $customerGroup)); + } + } + + Price::query() + ->where('priceable_type', $variant->getMorphClass()) + ->where('priceable_id', $variant->getKey()) + ->where('min_quantity', 1) + ->whereNotIn('id', $written) + ->get() + ->each(fn (Price $price) => $price->delete()); + + $variant->unsetRelation('prices'); + + return $bundle; + } + + /** + * Quantity-weighted sum of the components, each at its customer-group + * price when one exists, otherwise its base price. Null when a component + * has no base price in the currency. + * + * @param Collection $components + */ + protected function sum(Collection $components, Currency $currency, ?CustomerGroup $customerGroup): ?int + { + $sum = 0; + + foreach ($components as $component) { + $price = ($customerGroup ? $this->priceRow($component->variant, $currency, $customerGroup) : null) + ?? $this->priceRow($component->variant, $currency, null); + + if (! $price) { + return null; + } + + $sum += (int) $price->price * $component->quantity; + } + + return $sum; + } + + /** + * @param Collection $components + */ + protected function anyGroupPrice(Collection $components, Currency $currency, CustomerGroup $customerGroup): bool + { + return $components->contains( + fn (BundleComponent $component) => $this->priceRow($component->variant, $currency, $customerGroup) !== null + ); + } + + protected function priceRow(ProductVariant $variant, Currency $currency, ?CustomerGroup $customerGroup): ?Price + { + return $variant->prices->first( + fn (Price $price) => (int) $price->currency_id === (int) $currency->getKey() + && (int) $price->min_quantity === 1 + && $price->customer_group_id === $customerGroup?->getKey() + ); + } + + protected function write(Bundle $bundle, ProductVariant $variant, Currency $currency, ?CustomerGroup $customerGroup, int $sum): int + { + $discount = $bundle->discount_percentage + ? $this->calculator->percentage($sum, $bundle->discount_percentage / 100, $currency) + : 0; + + $price = Price::query()->firstOrNew([ + 'priceable_type' => $variant->getMorphClass(), + 'priceable_id' => $variant->getKey(), + 'currency_id' => $currency->getKey(), + 'customer_group_id' => $customerGroup?->getKey(), + 'min_quantity' => 1, + ]); + + $price->fill([ + 'price' => $sum - $discount, + 'list_price' => $discount > 0 ? $sum : null, + ])->save(); + + return (int) $price->getKey(); + } +} diff --git a/packages/bundles/src/Actions/ResolveBundleInventory.php b/packages/bundles/src/Actions/ResolveBundleInventory.php new file mode 100644 index 0000000000..6f53a4204a --- /dev/null +++ b/packages/bundles/src/Actions/ResolveBundleInventory.php @@ -0,0 +1,91 @@ +loadMissing('bundle')->bundle; + + if (! $bundle) { + return $this->inner->execute($variant); + } + + $bundle->loadMissing(['groups', 'components.variant']); + + // Answered through the inner action, never the component variant's own + // methods, which would re-enter this decorator. + $inventories = $bundle->components->mapWithKeys(fn (BundleComponent $component) => [ + $component->getKey() => $this->inner->execute($component->variant), + ]); + + $candidates = $this->candidates($bundle, $inventories); + + if ($candidates->isEmpty()) { + return new VariantInventory(available: 0, unlimited: false); + } + + return new VariantInventory( + available: (int) $candidates->min(fn (BundleComponent $component) => $this->completeUnits($component, $inventories)), + unlimited: $candidates->every(fn (BundleComponent $component) => $inventories[$component->getKey()]->unlimited), + ); + } + + /** + * Fixed components plus, per group, the best-stocked option: "available" + * means at least one valid configuration can be sold. + * + * @param Collection $inventories + * @return Collection + */ + protected function candidates(Bundle $bundle, Collection $inventories): Collection + { + $candidates = $bundle->components->filter(fn (BundleComponent $component) => $component->isFixed()); + + foreach ($bundle->groups as $group) { + $best = $bundle->components + ->where('bundle_group_id', $group->getKey()) + ->sortByDesc(fn (BundleComponent $component) => $inventories[$component->getKey()]->unlimited + ? PHP_INT_MAX + : $this->completeUnits($component, $inventories)) + ->first(); + + // A required group with nothing to choose from cannot be sold at all. + if (! $best && $group->min_selections > 0) { + return collect(); + } + + if ($best) { + $candidates->push($best); + } + } + + return $candidates->values(); + } + + /** + * @param Collection $inventories + */ + protected function completeUnits(BundleComponent $component, Collection $inventories): int + { + return intdiv(max(0, $inventories[$component->getKey()]->available), max(1, $component->quantity)); + } +} diff --git a/packages/bundles/src/Actions/ResolveBundleSelection.php b/packages/bundles/src/Actions/ResolveBundleSelection.php new file mode 100644 index 0000000000..79d4e9b5e9 --- /dev/null +++ b/packages/bundles/src/Actions/ResolveBundleSelection.php @@ -0,0 +1,122 @@ +loadMissing(['groups', 'components.variant']); + + $selections = $this->selectionsFrom($meta); + $groupIds = $bundle->groups->pluck('public_id'); + + foreach (array_keys($selections) as $publicId) { + if (! $groupIds->contains($publicId)) { + throw InvalidBundleSelection::unknownGroup((string) $publicId); + } + } + + /** @var Collection $chosen */ + $chosen = $bundle->components->where('bundle_group_id', null)->values(); + + foreach ($bundle->groups as $group) { + $chosen = $chosen->merge($this->resolveGroup($bundle, $group, $selections[$group->public_id] ?? null)); + } + + $defaultIds = $bundle->components + ->filter(fn (BundleComponent $component) => $component->isFixed() || $component->default) + ->pluck('id')->sort()->values(); + + $components = $chosen->map(fn (BundleComponent $component) => new SelectedComponent( + variant: $component->variant, + quantity: $component->quantity, + group: $component->bundle_group_id ? $bundle->groups->firstWhere('id', $component->bundle_group_id) : null, + component: $component, + )); + + return new BundleSelection( + components: $components->values(), + default: $chosen->pluck('id')->sort()->values()->all() === $defaultIds->all(), + ); + } + + /** + * @param array $meta + * @return array> + */ + protected function selectionsFrom(array $meta): array + { + $selections = $meta['bundle']['selections'] ?? []; + + if (! is_array($selections)) { + throw InvalidBundleSelection::malformed(); + } + + foreach ($selections as $ids) { + if (! is_array($ids)) { + throw InvalidBundleSelection::malformed(); + } + } + + return $selections; + } + + /** + * @param ?list $publicIds + * @return Collection + */ + protected function resolveGroup(Bundle $bundle, BundleGroup $group, ?array $publicIds): Collection + { + $name = (string) $group->translate('name'); + $options = $bundle->components->where('bundle_group_id', $group->getKey())->values(); + + if ($publicIds === null) { + if ($group->min_selections === 0) { + return collect(); + } + + $defaults = $options->where('default', true)->values(); + + if ($defaults->count() < $group->min_selections || $defaults->count() > $group->max_selections) { + throw InvalidBundleSelection::count($name, $group->min_selections, $group->max_selections); + } + + return $defaults; + } + + $publicIds = array_map('strval', $publicIds); + + if (count($publicIds) !== count(array_unique($publicIds))) { + throw InvalidBundleSelection::duplicateComponent($name); + } + + $chosen = collect($publicIds)->map(function (string $publicId) use ($options, $name) { + return $options->firstWhere('public_id', $publicId) + ?? throw InvalidBundleSelection::unknownComponent($publicId, $name); + }); + + if ($chosen->count() < $group->min_selections || $chosen->count() > $group->max_selections) { + throw InvalidBundleSelection::count($name, $group->min_selections, $group->max_selections); + } + + return $chosen; + } +} diff --git a/packages/bundles/src/Actions/SyncBundleComponents.php b/packages/bundles/src/Actions/SyncBundleComponents.php new file mode 100644 index 0000000000..5d7b1c5a45 --- /dev/null +++ b/packages/bundles/src/Actions/SyncBundleComponents.php @@ -0,0 +1,125 @@ +normalise($components); + + $this->guard($bundle, $rows); + + $bundle->getConnection()->transaction(function () use ($bundle, $rows) { + $existing = $bundle->components()->get(); + $kept = []; + + foreach ($rows as $row) { + /** @var BundleComponent $component */ + $component = $existing->first( + fn (BundleComponent $component) => $component->bundle_group_id === $row['bundle_group_id'] + && $component->product_variant_id === $row['product_variant_id'] + ) ?? $bundle->components()->make(); + + $component->fill($row)->save(); + + $kept[] = $component->getKey(); + } + + $existing->whereNotIn('id', $kept)->each(fn (BundleComponent $component) => $component->delete()); + }); + + $bundle->unsetRelation('components'); + $bundle->unsetRelation('fixedComponents'); + + return $this->reprice->execute($bundle); + } + + /** + * Collapse the input to plain column values, the last entry for a + * (group, variant) pair winning. + * + * @param list $components + * @return Collection + */ + protected function normalise(array $components): Collection + { + $rows = collect(); + + foreach (array_values($components) as $index => $component) { + $variantId = $component['variant'] instanceof ProductVariant + ? (int) $component['variant']->getKey() + : (int) $component['variant']; + + $group = $component['group'] ?? null; + $groupId = $group instanceof BundleGroup ? (int) $group->getKey() : ($group === null ? null : (int) $group); + + $rows["{$groupId}:{$variantId}"] = [ + 'bundle_group_id' => $groupId, + 'product_variant_id' => $variantId, + 'quantity' => max(1, (int) ($component['quantity'] ?? 1)), + 'default' => (bool) ($component['default'] ?? false), + 'position' => (int) ($component['position'] ?? $index), + ]; + } + + return $rows; + } + + /** + * @param Collection $rows + */ + protected function guard(Bundle $bundle, Collection $rows): void + { + if ($rows->isEmpty()) { + throw InvalidBundleDefinition::empty(); + } + + $max = (int) $this->config->get('lunar.bundles.max_components', 25); + + if ($rows->count() > $max) { + throw InvalidBundleDefinition::tooManyComponents($max); + } + + $variantIds = $rows->pluck('product_variant_id')->unique(); + + if ($variantIds->contains((int) $bundle->product_variant_id)) { + throw BundleNesting::self(); + } + + if (Bundle::query()->whereIn('product_variant_id', $variantIds)->exists()) { + throw BundleNesting::isBundle(); + } + + $groups = $bundle->loadMissing('groups')->groups; + $groupIds = $rows->pluck('bundle_group_id')->filter()->unique(); + + if ($groupIds->diff($groups->pluck('id'))->isNotEmpty()) { + throw InvalidBundleDefinition::unknownGroup(); + } + + foreach ($groups as $group) { + $count = $rows->where('bundle_group_id', (int) $group->getKey())->count(); + + if ($count > 0 && $group->max_selections > $count) { + throw InvalidBundleDefinition::groupSelections((string) $group->translate('name')); + } + } + } +} diff --git a/packages/bundles/src/Actions/SyncBundleGroups.php b/packages/bundles/src/Actions/SyncBundleGroups.php new file mode 100644 index 0000000000..b85db25716 --- /dev/null +++ b/packages/bundles/src/Actions/SyncBundleGroups.php @@ -0,0 +1,84 @@ +getConnection()->transaction(function () use ($bundle, $groups) { + $existing = $bundle->groups()->get(); + $kept = []; + + foreach (array_values($groups) as $index => $data) { + $name = $this->nameOf($data['name']); + $min = (int) $data['min_selections']; + $max = (int) $data['max_selections']; + + if ($min < 0 || $min > $max) { + throw InvalidBundleDefinition::groupSelections($name); + } + + /** @var ?BundleGroup $group */ + $group = isset($data['id']) ? $existing->firstWhere('id', (int) $data['id']) : null; + + if (isset($data['id']) && ! $group) { + throw InvalidBundleDefinition::unknownGroup(); + } + + $group ??= $bundle->groups()->make(); + + if ($group->exists) { + $count = $group->components()->count(); + + if ($count > 0 && $max > $count) { + throw InvalidBundleDefinition::groupSelections($name); + } + } + + $group->fill([ + 'name' => $data['name'], + 'min_selections' => $min, + 'max_selections' => $max, + 'position' => (int) ($data['position'] ?? $index), + ])->save(); + + $kept[] = $group->getKey(); + } + + $existing->whereNotIn('id', $kept)->each(function (BundleGroup $group) { + $group->components()->get()->each(fn (BundleComponent $component) => $component->delete()); + $group->delete(); + }); + }); + + $bundle->unsetRelation('groups'); + $bundle->unsetRelation('components'); + $bundle->unsetRelation('fixedComponents'); + + return $this->reprice->execute($bundle); + } + + /** + * @param array|string $name + */ + protected function nameOf(array|string $name): string + { + if (is_string($name)) { + return $name; + } + + return (string) ($name[app()->getLocale()] ?? reset($name) ?: ''); + } +} diff --git a/packages/bundles/src/BundlesServiceProvider.php b/packages/bundles/src/BundlesServiceProvider.php new file mode 100644 index 0000000000..5f838f805a --- /dev/null +++ b/packages/bundles/src/BundlesServiceProvider.php @@ -0,0 +1,168 @@ + default implementation. Consumers swap one by + * binding the same contract in their own service provider. + * + * @var array + */ + protected array $actions = [ + DefinesBundle::class => DefineBundle::class, + DeletesBundle::class => DeleteBundle::class, + RepricesBundle::class => RepriceBundle::class, + ResolvesBundleSelection::class => ResolveBundleSelection::class, + SyncsBundleComponents::class => SyncBundleComponents::class, + SyncsBundleGroups::class => SyncBundleGroups::class, + ]; + + public function register(): void + { + $this->mergeConfigFrom("{$this->root}/config/bundles.php", 'lunar.bundles'); + + foreach ($this->actions as $contract => $concrete) { + $this->app->bind($contract, $concrete); + } + + // A bundle variant's inventory is derived from its components; every + // other variant falls through to the core resolver. + $this->app->extend( + ResolvesInventory::class, + fn (ResolvesInventory $inner) => new ResolveBundleInventory($inner), + ); + } + + public function boot(): void + { + $this->publishes([ + "{$this->root}/config/bundles.php" => config_path('lunar/bundles.php'), + ], 'lunar.bundles.config'); + + if (! config('lunar.database.disable_migrations', false)) { + $this->loadMigrationsFrom("{$this->root}/database/migrations"); + } + + $this->loadTranslationsFrom("{$this->root}/resources/lang", 'bundles'); + + ModelManifest::addDirectory(__DIR__.'/Models'); + + Relation::morphMap([ + 'bundle' => Bundle::class, + 'bundle_group' => BundleGroup::class, + 'bundle_component' => BundleComponent::class, + ]); + + ProductVariant::resolveRelationUsing( + 'bundle', + fn (ProductVariant $variant) => $variant->hasOne(Bundle::class, 'product_variant_id'), + ); + + Product::resolveRelationUsing( + 'bundles', + fn (Product $product) => $product->hasManyThrough(Bundle::class, ProductVariant::class, 'product_id', 'product_variant_id'), + ); + + $this->registerCartHooks(); + $this->registerListeners(); + $this->registerConsole(); + $this->registerPanel(); + } + + /** + * Append the package's validator and stages to the core cart and order + * config. Hosts that set those lists explicitly keep control of the order. + */ + protected function registerCartHooks(): void + { + $append = function (string $key, string $class): void { + $entries = config($key, []); + + if (! in_array($class, $entries, true)) { + $entries[] = $class; + } + + config()->set($key, $entries); + }; + + $append('lunar.cart.validators.add_to_cart', BundleSelection::class); + $append('lunar.cart.validators.update_cart_line', BundleSelection::class); + $append('lunar.cart.pipelines.cart_lines', PriceBundleSelection::class); + $append('lunar.orders.pipelines.creation', CreateBundleComponentLines::class); + } + + protected function registerListeners(): void + { + Price::observe(RepriceOnComponentPriceChange::class); + Event::listen(ProductInvalidated::class, RepriceOnComponentInvalidation::class); + Event::listen(ProductInvalidated::class, InvalidateContainingBundles::class); + } + + protected function registerConsole(): void + { + if (! $this->app->runningInConsole()) { + return; + } + + $this->commands([ + RepriceBundlesCommand::class, + ]); + } + + /** The panel extension only exists when lunarphp/panel is installed and booted. */ + protected function registerPanel(): void + { + if (! class_exists(PanelManager::class) || ! $this->app->bound(PanelManager::class)) { + return; + } + + Panel::extendSection(new BundlesSectionExtension); + + $this->app->make(PanelManager::class)->vite('bundles', [ + 'input' => 'resources/js/addon.ts', + 'hotFile' => null, + 'buildDirectory' => 'vendor/lunar-panel/bundles', + '__buildSourcePath' => "{$this->root}/build", + ]); + } +} diff --git a/packages/bundles/src/Console/RepriceBundlesCommand.php b/packages/bundles/src/Console/RepriceBundlesCommand.php new file mode 100644 index 0000000000..722d4ebf76 --- /dev/null +++ b/packages/bundles/src/Console/RepriceBundlesCommand.php @@ -0,0 +1,44 @@ +where('pricing', BundlePricing::Components) + ->with('variant') + ->chunkById(100, function ($bundles) use ($reprice, &$count) { + foreach ($bundles as $bundle) { + $reprice->execute($bundle); + $count++; + } + }); + + $this->components->info(__('bundles::bundles.console.repriced', ['count' => $count])); + + return self::SUCCESS; + } +} diff --git a/packages/bundles/src/Contracts/Actions/DefinesBundle.php b/packages/bundles/src/Contracts/Actions/DefinesBundle.php new file mode 100644 index 0000000000..dcaa04b88c --- /dev/null +++ b/packages/bundles/src/Contracts/Actions/DefinesBundle.php @@ -0,0 +1,18 @@ + $meta + * + * @throws InvalidBundleSelection + */ + public function execute(Bundle $bundle, array $meta = []): BundleSelection; +} diff --git a/packages/bundles/src/Contracts/Actions/SyncsBundleComponents.php b/packages/bundles/src/Contracts/Actions/SyncsBundleComponents.php new file mode 100644 index 0000000000..3aaa951bc8 --- /dev/null +++ b/packages/bundles/src/Contracts/Actions/SyncsBundleComponents.php @@ -0,0 +1,22 @@ + $components + * + * @throws BundleNesting + * @throws InvalidBundleDefinition + */ + public function execute(Bundle $bundle, array $components): Bundle; +} diff --git a/packages/bundles/src/Contracts/Actions/SyncsBundleGroups.php b/packages/bundles/src/Contracts/Actions/SyncsBundleGroups.php new file mode 100644 index 0000000000..40c1c20c08 --- /dev/null +++ b/packages/bundles/src/Contracts/Actions/SyncsBundleGroups.php @@ -0,0 +1,19 @@ +, min_selections: int, max_selections: int, position?: int}> $groups + * + * @throws InvalidBundleDefinition + */ + public function execute(Bundle $bundle, array $groups): Bundle; +} diff --git a/packages/bundles/src/Enums/BundlePricing.php b/packages/bundles/src/Enums/BundlePricing.php new file mode 100644 index 0000000000..bab58b005b --- /dev/null +++ b/packages/bundles/src/Enums/BundlePricing.php @@ -0,0 +1,15 @@ + */ + public readonly array $cacheTags; + + public readonly string $morphType; + + public readonly int|string $cacheKey; + + public function __construct( + public Bundle $bundle, + public CacheInvalidationReason $reason, + ) { + $this->cacheTags = $bundle->cacheTags(); + $this->morphType = $bundle->getMorphClass(); + $this->cacheKey = $bundle->cacheKey(); + } + + /** @return array */ + public function cacheTags(): array + { + return $this->cacheTags; + } + + public function morphType(): string + { + return $this->morphType; + } + + public function cacheKey(): int|string + { + return $this->cacheKey; + } + + public function reason(): CacheInvalidationReason + { + return $this->reason; + } + + public function cacheModel(): Model + { + return $this->bundle; + } +} diff --git a/packages/bundles/src/Exceptions/BundleNesting.php b/packages/bundles/src/Exceptions/BundleNesting.php new file mode 100644 index 0000000000..fbeaeed097 --- /dev/null +++ b/packages/bundles/src/Exceptions/BundleNesting.php @@ -0,0 +1,26 @@ + $max])); + } + + public static function unknownGroup(): self + { + return new self(__('bundles::bundles.definition.unknown_group')); + } + + public static function groupSelections(string $group): self + { + return new self(__('bundles::bundles.definition.group_selections', ['group' => $group])); + } +} diff --git a/packages/bundles/src/Exceptions/InvalidBundleSelection.php b/packages/bundles/src/Exceptions/InvalidBundleSelection.php new file mode 100644 index 0000000000..b6759a0f7f --- /dev/null +++ b/packages/bundles/src/Exceptions/InvalidBundleSelection.php @@ -0,0 +1,36 @@ + $publicId])); + } + + public static function unknownComponent(string $publicId, string $group): self + { + return new self(__('bundles::bundles.selection.unknown_component', ['id' => $publicId, 'group' => $group])); + } + + public static function duplicateComponent(string $group): self + { + return new self(__('bundles::bundles.selection.duplicate_component', ['group' => $group])); + } + + public static function count(string $group, int $min, int $max): self + { + return new self(__('bundles::bundles.selection.count', ['group' => $group, 'min' => $min, 'max' => $max])); + } + + public static function malformed(): self + { + return new self(__('bundles::bundles.selection.malformed')); + } +} diff --git a/packages/bundles/src/Listeners/InvalidateContainingBundles.php b/packages/bundles/src/Listeners/InvalidateContainingBundles.php new file mode 100644 index 0000000000..ba9e904cc1 --- /dev/null +++ b/packages/bundles/src/Listeners/InvalidateContainingBundles.php @@ -0,0 +1,30 @@ +whereHas('components.variant', fn ($query) => $query->where('product_id', $event->product->getKey())) + ->with('variant.product') + ->get() + ->each(fn (Bundle $bundle) => $this->invalidator->record($bundle, CacheInvalidationReason::RelatedChanged)); + } +} diff --git a/packages/bundles/src/Listeners/RepriceOnComponentInvalidation.php b/packages/bundles/src/Listeners/RepriceOnComponentInvalidation.php new file mode 100644 index 0000000000..a042083c51 --- /dev/null +++ b/packages/bundles/src/Listeners/RepriceOnComponentInvalidation.php @@ -0,0 +1,29 @@ +where('pricing', BundlePricing::Components) + ->whereHas('components.variant', fn ($query) => $query->where('product_id', $event->product->getKey())) + ->get() + ->each(fn (Bundle $bundle) => $this->reprice->execute($bundle)); + } +} diff --git a/packages/bundles/src/Listeners/RepriceOnComponentPriceChange.php b/packages/bundles/src/Listeners/RepriceOnComponentPriceChange.php new file mode 100644 index 0000000000..ef30c2dcfd --- /dev/null +++ b/packages/bundles/src/Listeners/RepriceOnComponentPriceChange.php @@ -0,0 +1,44 @@ +repriceContaining($price); + } + + public function deleted(Price $price): void + { + $this->repriceContaining($price); + } + + protected function repriceContaining(Price $price): void + { + if ($price->priceable_type !== ProductVariant::morphName()) { + return; + } + + Bundle::query() + ->where('pricing', BundlePricing::Components) + ->whereHas('components', fn ($query) => $query->where('product_variant_id', $price->priceable_id)) + ->get() + ->each(fn (Bundle $bundle) => $this->reprice->execute($bundle)); + } +} diff --git a/packages/bundles/src/Models/Bundle.php b/packages/bundles/src/Models/Bundle.php new file mode 100644 index 0000000000..9766e7322b --- /dev/null +++ b/packages/bundles/src/Models/Bundle.php @@ -0,0 +1,131 @@ + BundlePricing::class, + 'discount_percentage' => 'float', + ]; + + protected static function newFactory(): BundleFactory + { + return BundleFactory::new(); + } + + /** The bundle variant: the sellable unit that carries the components. */ + public function variant(): BelongsTo + { + return $this->belongsTo(ProductVariant::class, 'product_variant_id'); + } + + public function groups(): HasMany + { + return $this->hasMany(BundleGroup::class)->orderBy('position')->orderBy('id'); + } + + public function components(): HasMany + { + return $this->hasMany(BundleComponent::class)->with('group')->orderBy('position')->orderBy('id'); + } + + public function fixedComponents(): HasMany + { + return $this->hasMany(BundleComponent::class)->whereNull('bundle_group_id')->orderBy('position')->orderBy('id'); + } + + /** A bundle with at least one group is configurable; with none it is fixed. */ + public function isConfigurable(): bool + { + return $this->loadMissing('groups')->groups->isNotEmpty(); + } + + /** + * A bundle has no cacheable page of its own; its product does. + * + * @return iterable + */ + public function cacheInvalidationTargets(): iterable + { + $this->loadMissing('variant.product'); + + return array_values(array_filter([$this->variant?->product])); + } + + public function newCacheInvalidationEvent(CacheInvalidationReason $reason): CacheInvalidationEvent + { + return new BundleInvalidated($this, $reason); + } + + /** + * @param list $components + */ + public function syncComponents(array $components): self + { + return app(SyncsBundleComponents::class)->execute($this, $components); + } + + /** + * @param list, min_selections: int, max_selections: int, position?: int}> $groups + */ + public function syncGroups(array $groups): self + { + return app(SyncsBundleGroups::class)->execute($this, $groups); + } + + public function reprice(): self + { + return app(RepricesBundle::class)->execute($this); + } + + /** + * @param array $meta + */ + public function resolveSelection(array $meta = []): BundleSelection + { + return app(ResolvesBundleSelection::class)->execute($this, $meta); + } +} diff --git a/packages/bundles/src/Models/BundleComponent.php b/packages/bundles/src/Models/BundleComponent.php new file mode 100644 index 0000000000..6fac81218f --- /dev/null +++ b/packages/bundles/src/Models/BundleComponent.php @@ -0,0 +1,80 @@ + 'integer', + 'default' => 'boolean', + 'position' => 'integer', + ]; + + protected static function newFactory(): BundleComponentFactory + { + return BundleComponentFactory::new(); + } + + public function bundle(): BelongsTo + { + return $this->belongsTo(Bundle::class); + } + + public function group(): BelongsTo + { + return $this->belongsTo(BundleGroup::class, 'bundle_group_id'); + } + + public function variant(): BelongsTo + { + return $this->belongsTo(ProductVariant::class, 'product_variant_id'); + } + + public function isFixed(): bool + { + return $this->bundle_group_id === null; + } + + /** @return iterable */ + public function cacheInvalidationTargets(): iterable + { + $this->loadMissing('bundle'); + + return $this->bundle ? [$this->bundle, ...$this->bundle->cacheInvalidationTargets()] : []; + } +} diff --git a/packages/bundles/src/Models/BundleGroup.php b/packages/bundles/src/Models/BundleGroup.php new file mode 100644 index 0000000000..5267005102 --- /dev/null +++ b/packages/bundles/src/Models/BundleGroup.php @@ -0,0 +1,74 @@ + AsArrayObject::class, + 'min_selections' => 'integer', + 'max_selections' => 'integer', + 'position' => 'integer', + ]; + + protected static function newFactory(): BundleGroupFactory + { + return BundleGroupFactory::new(); + } + + public function bundle(): BelongsTo + { + return $this->belongsTo(Bundle::class); + } + + public function components(): HasMany + { + return $this->hasMany(BundleComponent::class)->orderBy('position')->orderBy('id'); + } + + /** @return iterable */ + public function cacheInvalidationTargets(): iterable + { + $this->loadMissing('bundle'); + + return $this->bundle ? [$this->bundle, ...$this->bundle->cacheInvalidationTargets()] : []; + } +} diff --git a/packages/bundles/src/Panel/BundleSummary.php b/packages/bundles/src/Panel/BundleSummary.php new file mode 100644 index 0000000000..75bdeb9f14 --- /dev/null +++ b/packages/bundles/src/Panel/BundleSummary.php @@ -0,0 +1,179 @@ + + */ + public function for(ProductVariant $variant): array + { + $variant->loadMissing(['product.thumbnail', 'images', 'values.option', 'bundle']); + + /** @var ?Bundle $bundle */ + $bundle = $variant->bundle; + + return [ + 'variant' => $this->variantRow($variant), + 'defined' => $bundle !== null, + 'bundle' => $bundle ? $this->bundle($bundle, $variant) : null, + 'default_language' => Language::query()->where('default', true)->value('code') ?? config('app.locale'), + 'urls' => [ + 'show' => route('panel.bundles.variants.show', $variant), + 'define' => route('panel.bundles.variants.update', $variant), + 'destroy' => route('panel.bundles.variants.destroy', $variant), + 'components' => route('panel.bundles.variants.components', $variant), + 'groups' => route('panel.bundles.variants.groups', $variant), + 'search' => route('panel.bundles.search-variants', ['exclude' => $variant->getKey()]), + ], + ]; + } + + /** + * The picker row and the component row share this shape so a variant + * reads the same before and after it is added. + * + * @return array{id: int, public_id: string, sku: ?string, name: string, option: ?string, thumbnail: ?string, edit_url: string} + */ + public function variantRow(ProductVariant $variant): array + { + $variant->loadMissing(['product.thumbnail', 'images', 'values.option']); + + return [ + 'id' => (int) $variant->getKey(), + 'public_id' => (string) $variant->public_id, + 'sku' => $variant->sku, + 'name' => (string) $variant->product?->translate('name'), + 'option' => $this->optionLabel($variant), + 'thumbnail' => $variant->getThumbnailImage() ?: null, + 'edit_url' => route('panel.products.variants.edit', [$variant->product_id, $variant->getKey()]), + ]; + } + + /** + * @return array + */ + protected function bundle(Bundle $bundle, ProductVariant $variant): array + { + $bundle->loadMissing(['groups', 'components.variant.product.thumbnail', 'components.variant.images', 'components.variant.values.option', 'components.variant.prices']); + + $inventory = $this->inventory->execute($variant); + + return [ + 'id' => (int) $bundle->getKey(), + 'pricing' => $bundle->pricing->value, + 'discount_percentage' => $bundle->discount_percentage, + 'configurable' => $bundle->groups->isNotEmpty(), + 'components' => $bundle->components->map(fn (BundleComponent $component) => [ + 'id' => (int) $component->getKey(), + 'public_id' => (string) $component->public_id, + 'group_id' => $component->bundle_group_id ? (int) $component->bundle_group_id : null, + 'quantity' => (int) $component->quantity, + 'default' => (bool) $component->default, + 'position' => (int) $component->position, + 'variant' => $this->variantRow($component->variant), + ])->values()->all(), + 'groups' => $bundle->groups->map(fn (BundleGroup $group) => [ + 'id' => (int) $group->getKey(), + 'public_id' => (string) $group->public_id, + 'name' => $group->name?->getArrayCopy() ?: (object) [], + 'label' => (string) $group->translate('name'), + 'min_selections' => (int) $group->min_selections, + 'max_selections' => (int) $group->max_selections, + 'position' => (int) $group->position, + ])->values()->all(), + 'availability' => [ + 'available' => $inventory->available, + 'unlimited' => $inventory->unlimited, + ], + 'prices' => $bundle->pricing === BundlePricing::Components ? $this->derivedPrices($bundle, $variant) : [], + ]; + } + + /** + * Per currency: the materialised base price when every default-selection + * component has a base price, otherwise the components that lack one. + * + * @return array}> + */ + protected function derivedPrices(Bundle $bundle, ProductVariant $variant): array + { + $variant->loadMissing('prices'); + + $components = $bundle->components + ->filter(fn (BundleComponent $component) => $component->isFixed() || $component->default) + ->values(); + + return Currency::query()->orderByDesc('default')->orderBy('code')->get() + ->map(function (Currency $currency) use ($components, $variant) { + $missing = $components + ->reject(fn (BundleComponent $component) => $this->basePrice($component->variant->prices, $currency) !== null) + ->map(fn (BundleComponent $component) => $this->componentLabel($component->variant)) + ->values() + ->all(); + + $price = $missing === [] ? $this->basePrice($variant->prices, $currency) : null; + + return [ + 'currency' => $currency->code, + 'price' => $price ? (new PriceValue((int) $price->price, $currency))->format() : null, + 'list_price' => $price?->list_price ? (new PriceValue((int) $price->list_price, $currency))->format() : null, + 'missing' => $missing, + ]; + }) + ->values() + ->all(); + } + + /** + * @param Collection $prices + */ + protected function basePrice(Collection $prices, Currency $currency): ?Price + { + return $prices->first( + fn (Price $price) => (int) $price->currency_id === (int) $currency->getKey() + && (int) $price->min_quantity === 1 + && $price->customer_group_id === null + ); + } + + protected function optionLabel(ProductVariant $variant): ?string + { + $label = $variant->values + ->map(fn (ProductOptionValue $value) => $value->translate('name')) + ->filter() + ->implode(' / '); + + return $label !== '' ? $label : null; + } + + protected function componentLabel(ProductVariant $variant): string + { + $name = (string) $variant->product?->translate('name'); + $option = $this->optionLabel($variant); + + return $option ? "{$name} ({$option})" : ($name !== '' ? $name : (string) $variant->sku); + } +} diff --git a/packages/bundles/src/Panel/BundlesSectionExtension.php b/packages/bundles/src/Panel/BundlesSectionExtension.php new file mode 100644 index 0000000000..fc3e57423a --- /dev/null +++ b/packages/bundles/src/Panel/BundlesSectionExtension.php @@ -0,0 +1,83 @@ +name('panel.bundles.') + ->middleware('can:'.CatalogSection::PRODUCTS_PERMISSION) + ->group(function (): void { + Route::get('/search-variants', [VariantSearchController::class, 'search'])->name('search-variants'); + + Route::get('/variants/{variant}', [BundleController::class, 'show'])->name('variants.show'); + Route::put('/variants/{variant}', [BundleController::class, 'update'])->name('variants.update'); + Route::delete('/variants/{variant}', [BundleController::class, 'destroy'])->name('variants.destroy'); + Route::put('/variants/{variant}/components', [BundleComponentsController::class, 'update'])->name('variants.components'); + Route::put('/variants/{variant}/groups', [BundleGroupsController::class, 'update'])->name('variants.groups'); + + Route::get('/products/{product}', [ProductBundlesController::class, 'show'])->name('products.show'); + Route::get('/products/{product}/included-in', [ProductBundlesController::class, 'includedIn'])->name('products.included-in'); + }); + }; + } + + public function slots(SlotRegistry $registry): void + { + $registry->add(new Slot( + zone: 'products.edit:variants:after', + component: 'bundles::BundleCard', + permission: CatalogSection::PRODUCTS_PERMISSION, + )); + + $registry->add(new Slot( + zone: 'products.variants.edit:main:after', + component: 'bundles::BundleCard', + permission: CatalogSection::PRODUCTS_PERMISSION, + )); + + $registry->add(new Slot( + zone: 'products.edit:sidebar:after', + component: 'bundles::IncludedInBundlesCard', + permission: CatalogSection::PRODUCTS_PERMISSION, + )); + } + + /** @return array */ + public function tableExtensions(): array + { + return ['products.index' => ProductsTableExtension::class]; + } + + /** @return array */ + public function langNamespaces(): array + { + return ['bundles']; + } +} diff --git a/packages/bundles/src/Panel/Http/Controllers/BundleComponentsController.php b/packages/bundles/src/Panel/Http/Controllers/BundleComponentsController.php new file mode 100644 index 0000000000..f5da407c19 --- /dev/null +++ b/packages/bundles/src/Panel/Http/Controllers/BundleComponentsController.php @@ -0,0 +1,36 @@ +bundle($variant); + + $components = collect($request->validated('components', [])) + ->values() + ->map(fn (array $component, int $index) => [ + 'variant' => (int) $component['variant_id'], + 'quantity' => (int) ($component['quantity'] ?? 1), + 'group' => isset($component['group_id']) ? (int) $component['group_id'] : null, + 'default' => (bool) ($component['default'] ?? false), + 'position' => (int) ($component['position'] ?? $index), + ]) + ->all(); + + $this->guarded('components', fn () => $bundle->syncComponents($components)); + + $variant->unsetRelation('bundle'); + + return response()->json($summary->for($variant)); + } +} diff --git a/packages/bundles/src/Panel/Http/Controllers/BundleController.php b/packages/bundles/src/Panel/Http/Controllers/BundleController.php new file mode 100644 index 0000000000..6b347d528e --- /dev/null +++ b/packages/bundles/src/Panel/Http/Controllers/BundleController.php @@ -0,0 +1,49 @@ +json($summary->for($variant)); + } + + public function update(DefineBundleRequest $request, ProductVariant $variant, DefinesBundle $define, BundleSummary $summary): JsonResponse + { + $discount = $request->input('discount_percentage'); + + $this->guarded('bundle', fn () => $define->execute( + $variant, + BundlePricing::from($request->string('pricing')->value()), + $discount === null || $discount === '' ? null : (float) $discount, + )); + + $variant->unsetRelation('bundle'); + + return response()->json($summary->for($variant)); + } + + public function destroy(ProductVariant $variant, DeletesBundle $delete, BundleSummary $summary): JsonResponse + { + $variant->loadMissing('bundle'); + + if ($variant->bundle) { + $delete->execute($variant->bundle); + $variant->unsetRelation('bundle'); + } + + return response()->json($summary->for($variant)); + } +} diff --git a/packages/bundles/src/Panel/Http/Controllers/BundleGroupsController.php b/packages/bundles/src/Panel/Http/Controllers/BundleGroupsController.php new file mode 100644 index 0000000000..df9200fa29 --- /dev/null +++ b/packages/bundles/src/Panel/Http/Controllers/BundleGroupsController.php @@ -0,0 +1,36 @@ +bundle($variant); + + $groups = collect($request->validated('groups', [])) + ->values() + ->map(fn (array $group, int $index) => array_filter([ + 'id' => isset($group['id']) ? (int) $group['id'] : null, + 'name' => array_filter($group['name'], fn ($value) => $value !== null && $value !== ''), + 'min_selections' => (int) $group['min_selections'], + 'max_selections' => (int) $group['max_selections'], + 'position' => (int) ($group['position'] ?? $index), + ], fn ($value) => $value !== null)) + ->all(); + + $this->guarded('groups', fn () => $bundle->syncGroups($groups)); + + $variant->unsetRelation('bundle'); + + return response()->json($summary->for($variant)); + } +} diff --git a/packages/bundles/src/Panel/Http/Controllers/Concerns/TranslatesBundleExceptions.php b/packages/bundles/src/Panel/Http/Controllers/Concerns/TranslatesBundleExceptions.php new file mode 100644 index 0000000000..37ecbe5667 --- /dev/null +++ b/packages/bundles/src/Panel/Http/Controllers/Concerns/TranslatesBundleExceptions.php @@ -0,0 +1,30 @@ + [$exception->getMessage()]]); + } + } +} diff --git a/packages/bundles/src/Panel/Http/Controllers/ProductBundlesController.php b/packages/bundles/src/Panel/Http/Controllers/ProductBundlesController.php new file mode 100644 index 0000000000..38c1d25faf --- /dev/null +++ b/packages/bundles/src/Panel/Http/Controllers/ProductBundlesController.php @@ -0,0 +1,63 @@ +variants() + ->with(['product.thumbnail', 'images', 'values.option', 'bundle']) + ->orderBy('id') + ->get() + ->map(fn (ProductVariant $variant) => $summary->for($variant)) + ->values(); + + return response()->json(['variants' => $variants]); + } + + /** + * Bundles that include any of this product's variants, each linking to + * its own product: the merchant's warning before deleting a component. + */ + public function includedIn(Product $product, BundleSummary $summary): JsonResponse + { + $variantIds = $product->variants()->pluck('id'); + + $bundles = Bundle::query() + ->whereHas('components', fn ($query) => $query->whereIn('product_variant_id', $variantIds)) + ->with([ + 'variant.product.thumbnail', + 'variant.images', + 'variant.values.option', + 'components' => fn ($query) => $query + ->whereIn('product_variant_id', $variantIds) + ->with(['variant.product.thumbnail', 'variant.images', 'variant.values.option']), + ]) + ->get() + ->map(fn (Bundle $bundle) => [ + 'id' => (int) $bundle->getKey(), + 'variant' => $summary->variantRow($bundle->variant), + 'product_url' => route('panel.products.edit', $bundle->variant->product_id), + 'components' => $bundle->components->map(fn (BundleComponent $component) => [ + 'quantity' => (int) $component->quantity, + 'variant' => $summary->variantRow($component->variant), + ])->values()->all(), + ]) + ->values(); + + return response()->json(['data' => $bundles]); + } +} diff --git a/packages/bundles/src/Panel/Http/Controllers/VariantSearchController.php b/packages/bundles/src/Panel/Http/Controllers/VariantSearchController.php new file mode 100644 index 0000000000..ab08e858f0 --- /dev/null +++ b/packages/bundles/src/Panel/Http/Controllers/VariantSearchController.php @@ -0,0 +1,54 @@ +string('q')->value(); + + $variants = ProductVariant::query() + ->with(['product.thumbnail', 'images', 'values.option']) + ->whereNotIn('id', Bundle::query()->select('product_variant_id')) + ->when($request->filled('exclude'), fn ($query) => $query->whereKeyNot($request->integer('exclude'))) + ->when($term !== '', function ($query) use ($term) { + $like = "%{$term}%"; + + $query->where(function ($query) use ($like) { + // The dedicated name column holds a {locale: text} map. + $query->where('sku', 'like', $like) + ->orWhereHas('product', fn ($query) => $query->where('name', 'like', $like)); + }); + }) + ->orderBy('id') + ->limit(20) + ->get() + ->map(function (ProductVariant $variant) use ($summary) { + $row = $summary->variantRow($variant); + + return [ + ...$row, + 'kind' => 'variants', + 'label' => $row['option'] ? "{$row['name']} ({$row['option']})" : $row['name'], + 'hint' => $row['sku'], + 'is_bundle' => false, + ]; + }) + ->values(); + + return response()->json(['data' => $variants]); + } +} diff --git a/packages/bundles/src/Panel/Http/Requests/Concerns/RequiresBundle.php b/packages/bundles/src/Panel/Http/Requests/Concerns/RequiresBundle.php new file mode 100644 index 0000000000..7ee2a9d488 --- /dev/null +++ b/packages/bundles/src/Panel/Http/Requests/Concerns/RequiresBundle.php @@ -0,0 +1,30 @@ +loadMissing('bundle'); + + /** @var ?Bundle $bundle */ + $bundle = $variant->bundle; + + if (! $bundle) { + throw ValidationException::withMessages([ + 'bundle' => [__('bundles::bundles.panel.not_defined')], + ]); + } + + return $bundle; + } +} diff --git a/packages/bundles/src/Panel/Http/Requests/DefineBundleRequest.php b/packages/bundles/src/Panel/Http/Requests/DefineBundleRequest.php new file mode 100644 index 0000000000..0ec856de15 --- /dev/null +++ b/packages/bundles/src/Panel/Http/Requests/DefineBundleRequest.php @@ -0,0 +1,19 @@ +> */ + public function rules(): array + { + return [ + 'pricing' => ['required', Rule::enum(BundlePricing::class)], + 'discount_percentage' => ['nullable', 'numeric', 'min:0', 'max:100'], + ]; + } +} diff --git a/packages/bundles/src/Panel/Http/Requests/SyncBundleComponentsRequest.php b/packages/bundles/src/Panel/Http/Requests/SyncBundleComponentsRequest.php new file mode 100644 index 0000000000..7c02e35fa4 --- /dev/null +++ b/packages/bundles/src/Panel/Http/Requests/SyncBundleComponentsRequest.php @@ -0,0 +1,26 @@ +> */ + public function rules(): array + { + return [ + 'components' => ['present', 'array'], + 'components.*.variant_id' => ['required', 'integer', 'exists:'.(new ProductVariant)->getTable().',id'], + 'components.*.quantity' => ['required', 'integer', 'min:1'], + 'components.*.group_id' => ['nullable', 'integer', 'exists:'.(new BundleGroup)->getTable().',id'], + 'components.*.default' => ['sometimes', 'boolean'], + 'components.*.position' => ['sometimes', 'integer', 'min:0'], + ]; + } +} diff --git a/packages/bundles/src/Panel/Http/Requests/SyncBundleGroupsRequest.php b/packages/bundles/src/Panel/Http/Requests/SyncBundleGroupsRequest.php new file mode 100644 index 0000000000..674a7e15ac --- /dev/null +++ b/packages/bundles/src/Panel/Http/Requests/SyncBundleGroupsRequest.php @@ -0,0 +1,26 @@ +> */ + public function rules(): array + { + return [ + 'groups' => ['present', 'array'], + 'groups.*.id' => ['nullable', 'integer', 'exists:'.(new BundleGroup)->getTable().',id'], + 'groups.*.name' => ['required', 'array'], + 'groups.*.name.*' => ['nullable', 'string', 'max:255'], + 'groups.*.min_selections' => ['required', 'integer', 'min:0'], + 'groups.*.max_selections' => ['required', 'integer', 'min:1'], + 'groups.*.position' => ['sometimes', 'integer', 'min:0'], + ]; + } +} diff --git a/packages/bundles/src/Panel/Tables/BundleColumn.php b/packages/bundles/src/Panel/Tables/BundleColumn.php new file mode 100644 index 0000000000..26face8302 --- /dev/null +++ b/packages/bundles/src/Panel/Tables/BundleColumn.php @@ -0,0 +1,34 @@ +withExists('bundles as is_bundle'); + } +} diff --git a/packages/bundles/src/Panel/Tables/BundlesOnlyFilter.php b/packages/bundles/src/Panel/Tables/BundlesOnlyFilter.php new file mode 100644 index 0000000000..148d046316 --- /dev/null +++ b/packages/bundles/src/Panel/Tables/BundlesOnlyFilter.php @@ -0,0 +1,34 @@ + */ + public function options(): array + { + return [ + 'only' => __('bundles::bundles.panel.filter_only'), + ]; + } + + public function query(Builder $query, mixed $value): void + { + if ($value === 'only') { + $query->whereHas('bundles'); + } + } +} diff --git a/packages/bundles/src/Panel/Tables/ProductsTableExtension.php b/packages/bundles/src/Panel/Tables/ProductsTableExtension.php new file mode 100644 index 0000000000..a31082fea4 --- /dev/null +++ b/packages/bundles/src/Panel/Tables/ProductsTableExtension.php @@ -0,0 +1,20 @@ + */ + public function columns(): array + { + return [BundleColumn::class]; + } + + /** @return array */ + public function filters(): array + { + return [BundlesOnlyFilter::class]; + } +} diff --git a/packages/bundles/src/Pipelines/CartLine/PriceBundleSelection.php b/packages/bundles/src/Pipelines/CartLine/PriceBundleSelection.php new file mode 100644 index 0000000000..1d19ea6ca0 --- /dev/null +++ b/packages/bundles/src/Pipelines/CartLine/PriceBundleSelection.php @@ -0,0 +1,92 @@ +purchasable; + + if (! $purchasable instanceof ProductVariant) { + return $next($cartLine); + } + + /** @var ?Bundle $bundle */ + $bundle = $purchasable->loadMissing('bundle')->bundle; + + if (! $bundle || $bundle->pricing !== BundlePricing::Components) { + return $next($cartLine); + } + + $meta = $cartLine->meta instanceof ArrayObject ? $cartLine->meta->getArrayCopy() : (array) $cartLine->meta; + $selection = $this->resolver->execute($bundle, $meta); + + if ($selection->isDefault()) { + return $next($cartLine); + } + + $cart = $cartLine->cart; + $currency = $cart->currency; + $customerGroups = $this->customerGroupsFor($cart); + $sum = 0; + + foreach ($selection as $component) { + /** @var SelectedComponent $component */ + $matched = $this->pricing + ->currency($currency) + ->qty(1) + ->customerGroups($customerGroups) + ->for($component->variant) + ->get() + ->matched; + + $sum += (int) $matched->price * $component->quantity; + } + + $discount = $bundle->discount_percentage + ? $this->calculator->percentage($sum, $bundle->discount_percentage / 100, $currency) + : 0; + + // A transient row so tax is added exactly as it is for a stored price. + $price = new Price(['price' => $sum - $discount, 'currency_id' => $currency->getKey()]); + $price->setRelation('currency', $currency); + $price->setRelation('priceable', $purchasable); + + $cartLine->unitPrice = new PriceValue($sum - $discount, $currency); + $cartLine->unitPriceInclTax = new PriceValue($price->priceIncTax($cart->taxZone)->value, $currency); + + return $next($cartLine); + } +} diff --git a/packages/bundles/src/Pipelines/Order/Creation/CreateBundleComponentLines.php b/packages/bundles/src/Pipelines/Order/Creation/CreateBundleComponentLines.php new file mode 100644 index 0000000000..cbe2537480 --- /dev/null +++ b/packages/bundles/src/Pipelines/Order/Creation/CreateBundleComponentLines.php @@ -0,0 +1,143 @@ +loadMissing(['lines.purchasable', 'currency', 'cart']); + + foreach ($order->lines->whereNull('parent_line_id') as $line) { + $variant = $line->purchasable; + + if (! $variant instanceof ProductVariant) { + continue; + } + + /** @var ?Bundle $bundle */ + $bundle = $variant->loadMissing('bundle')->bundle; + + if (! $bundle) { + continue; + } + + $this->createComponentLines($order, $line, $bundle); + } + + $order->unsetRelation('lines'); + + return $next($order); + } + + protected function createComponentLines(Order $order, OrderLine $parent, Bundle $bundle): void + { + $parent->forceFill([ + 'type' => 'bundle', + 'requires_fulfilment' => false, + ])->save(); + + $parent->components()->get()->each(fn (OrderLine $component) => $component->delete()); + + $meta = $parent->meta instanceof ArrayObject ? $parent->meta->getArrayCopy() : (array) $parent->meta; + $selection = $this->resolver->execute($bundle, $meta); + + $bundle->loadMissing(['components.variant.product', 'components.variant.values']); + + $currency = $order->currency; + $customerGroups = $this->customerGroupsFor($order->cart); + $weights = []; + $attributes = []; + + foreach ($selection->components as $index => $component) { + /** @var SelectedComponent $component */ + $variant = $component->variant; + $quantity = $component->quantity * $parent->quantity; + + $weights[$index] = $this->currentUnitPrice($variant, $customerGroups) * $quantity; + + $attributes[$index] = [ + 'purchasable_type' => $variant->getMorphClass(), + 'purchasable_id' => $variant->getKey(), + 'type' => $variant->getType(), + 'requires_shipping' => $variant->isShippable(), + 'requires_fulfilment' => $variant->requiresFulfilment(), + 'description' => $variant->getDescription(), + 'option' => $variant->getOption(), + 'identifier' => $variant->getIdentifier(), + 'unit_price' => 0, + 'unit_quantity' => $variant->getUnitQuantity(), + 'quantity' => $quantity, + 'sub_total' => 0, + 'discount_total' => 0, + 'tax_breakdown' => new TaxBreakdown, + 'tax_total' => 0, + 'total' => 0, + 'notes' => null, + ]; + } + + // Reporting only: the parent's total spread across the parts in + // proportion to their current prices, exact to the minor unit. + $allocated = $this->calculator->distribute((int) $parent->total, $weights, $currency); + + foreach ($attributes as $index => $lineAttributes) { + $parent->components()->create($lineAttributes + [ + 'order_id' => $order->getKey(), + 'meta' => ['allocated_total' => $allocated[$index] ?? 0], + ]); + } + } + + /** + * @param Collection $customerGroups + */ + protected function currentUnitPrice(ProductVariant $variant, $customerGroups): int + { + try { + return (int) $this->pricing + ->qty(1) + ->customerGroups($customerGroups) + ->for($variant) + ->get() + ->matched + ->price; + } catch (MissingCurrencyPriceException) { + return 0; + } + } +} diff --git a/packages/bundles/src/Support/ResolvesCartCustomerGroups.php b/packages/bundles/src/Support/ResolvesCartCustomerGroups.php new file mode 100644 index 0000000000..0f02c1c3cc --- /dev/null +++ b/packages/bundles/src/Support/ResolvesCartCustomerGroups.php @@ -0,0 +1,30 @@ + */ + protected function customerGroupsFor(Cart $cart): Collection + { + $cart->loadMissing('customer.customerGroups'); + + if ($cart->customer) { + return $cart->customer->customerGroups; + } + + $cart->loadMissing('user'); + $cart->user?->loadMissing('customers.customerGroups'); + + return collect($cart->user?->customers->pluck('customerGroups')->flatten()); + } +} diff --git a/packages/bundles/src/Validation/CartLine/BundleSelection.php b/packages/bundles/src/Validation/CartLine/BundleSelection.php new file mode 100644 index 0000000000..1e49bd4e77 --- /dev/null +++ b/packages/bundles/src/Validation/CartLine/BundleSelection.php @@ -0,0 +1,91 @@ +parameters['cart'] ?? null; + $purchasable = $this->parameters['purchasable'] ?? null; + $cartLineId = $this->parameters['cartLineId'] ?? null; + $quantity = (int) ($this->parameters['quantity'] ?? 0); + $line = null; + + if (! $purchasable && $cartLineId && $cart) { + /** @var ?CartLine $line */ + $line = $cart->lines->first(fn (CartLine $cartLine) => $cartLine->id == $cartLineId); + $purchasable = $line?->purchasable; + } + + if (! $purchasable instanceof ProductVariant) { + return $this->pass(); + } + + /** @var ?Bundle $bundle */ + $bundle = $purchasable->loadMissing('bundle')->bundle; + + if (! $bundle) { + return $this->pass(); + } + + try { + $selection = $this->resolver->execute($bundle, $this->metaFor($line)); + } catch (InvalidBundleSelection $exception) { + return $this->fail('cart', $exception->getMessage()); + } + + foreach ($selection as $component) { + /** @var SelectedComponent $component */ + if (! $component->variant->canBeFulfilledAtQuantity($component->quantity * $quantity)) { + return $this->fail('cart', __('bundles::bundles.selection.unavailable', [ + 'identifier' => $component->variant->getIdentifier(), + ])); + } + } + + return $this->pass(); + } + + /** + * The meta the line will carry after the action runs: `UpdateCartLine` + * replaces the line's meta when a non-empty one is given, so an update + * with no meta is validated against what the line already holds. + * + * @return array + */ + protected function metaFor(?CartLine $line): array + { + $incoming = $this->parameters['meta'] ?? null; + + if ($incoming instanceof ArrayObject) { + $incoming = $incoming->getArrayCopy(); + } + + if (is_array($incoming) && $incoming !== []) { + return $incoming; + } + + $current = $line?->meta; + + return $current instanceof ArrayObject ? $current->getArrayCopy() : (array) $current; + } +} diff --git a/packages/bundles/src/ValueObjects/BundleSelection.php b/packages/bundles/src/ValueObjects/BundleSelection.php new file mode 100644 index 0000000000..2efb2e031a --- /dev/null +++ b/packages/bundles/src/ValueObjects/BundleSelection.php @@ -0,0 +1,73 @@ + + */ +final readonly class BundleSelection implements Countable, IteratorAggregate +{ + /** + * @param Collection $components + * @param bool $default whether this is exactly the bundle's default selection + */ + public function __construct( + public Collection $components, + private bool $default, + ) {} + + public function isDefault(): bool + { + return $this->default; + } + + /** @return Collection */ + public function variants(): Collection + { + return $this->components->map(fn (SelectedComponent $component) => $component->variant); + } + + /** + * @param callable(SelectedComponent): mixed $callback + */ + public function each(callable $callback): self + { + $this->components->each($callback); + + return $this; + } + + /** + * @template T + * + * @param callable(SelectedComponent): T $callback + * @return Collection + */ + public function map(callable $callback): Collection + { + return $this->components->map($callback); + } + + public function isEmpty(): bool + { + return $this->components->isEmpty(); + } + + public function count(): int + { + return $this->components->count(); + } + + public function getIterator(): Traversable + { + return $this->components->getIterator(); + } +} diff --git a/packages/bundles/src/ValueObjects/SelectedComponent.php b/packages/bundles/src/ValueObjects/SelectedComponent.php new file mode 100644 index 0000000000..98c5d190b5 --- /dev/null +++ b/packages/bundles/src/ValueObjects/SelectedComponent.php @@ -0,0 +1,21 @@ +bigIncrements('id'); $table->ulid('public_id')->unique(); $table->foreignId('order_id')->constrained($this->prefix.'orders'); + $table->foreignId('parent_line_id')->nullable()->index()->constrained($this->prefix.'order_lines')->cascadeOnDelete()->comment('Set on a component line that belongs to another line (a bundle part); never priced'); $table->nullableMorphs('purchasable'); $table->string('type')->index(); $table->boolean('requires_shipping')->default(false)->index()->comment('Needs physical delivery; stamped from the purchasable isShippable()'); diff --git a/packages/core/src/ActionServiceProvider.php b/packages/core/src/ActionServiceProvider.php index b3959d4164..3b8b9189d8 100644 --- a/packages/core/src/ActionServiceProvider.php +++ b/packages/core/src/ActionServiceProvider.php @@ -109,6 +109,7 @@ use Lunar\Core\Actions\Products\RecordStockMovement; use Lunar\Core\Actions\Products\ReleaseReservation; use Lunar\Core\Actions\Products\ReserveStock; +use Lunar\Core\Actions\Products\ResolveInventory; use Lunar\Core\Actions\Products\SyncStockCommitment; use Lunar\Core\Actions\Products\UpdateProduct; use Lunar\Core\Actions\Products\UpdateProductStatus; @@ -243,6 +244,7 @@ class ActionServiceProvider extends ServiceProvider Contracts\Products\RecomputesStockRollup::class => RecomputeStockRollup::class, Contracts\Products\RecordsStockMovement::class => RecordStockMovement::class, Contracts\Products\ReleasesReservation::class => ReleaseReservation::class, + Contracts\Products\ResolvesInventory::class => ResolveInventory::class, Contracts\Products\ReservesStock::class => ReserveStock::class, Contracts\Products\SyncsStockCommitment::class => SyncStockCommitment::class, Contracts\Products\MapsVariantsToProductOptions::class => MapVariantsToProductOptions::class, diff --git a/packages/core/src/Actions/Products/ResolveInventory.php b/packages/core/src/Actions/Products/ResolveInventory.php new file mode 100644 index 0000000000..f11154b015 --- /dev/null +++ b/packages/core/src/Actions/Products/ResolveInventory.php @@ -0,0 +1,25 @@ +selling_policy) { + SellingPolicy::Always, SellingPolicy::InStock => (int) $variant->stock_available, + SellingPolicy::InStockOrOnBackorder => (int) $variant->stock_available + (int) $variant->backorder, + }, + unlimited: $variant->selling_policy === SellingPolicy::Always, + ); + } +} diff --git a/packages/core/src/Contracts/Actions/Products/ResolvesInventory.php b/packages/core/src/Contracts/Actions/Products/ResolvesInventory.php new file mode 100644 index 0000000000..1dfda5313e --- /dev/null +++ b/packages/core/src/Contracts/Actions/Products/ResolvesInventory.php @@ -0,0 +1,18 @@ +unlimited || $quantity <= $this->available; + } +} diff --git a/packages/core/src/Models/OrderLine.php b/packages/core/src/Models/OrderLine.php index 43c284edfb..3b347f162f 100644 --- a/packages/core/src/Models/OrderLine.php +++ b/packages/core/src/Models/OrderLine.php @@ -22,6 +22,7 @@ * @property int $id * @property string $public_id * @property int $order_id + * @property ?int $parent_line_id * @property string $purchasable_type * @property int $purchasable_id * @property string $type @@ -100,6 +101,34 @@ public function order(): BelongsTo return $this->belongsTo(Order::class); } + /** + * The line this one is a component of. Component lines are the parts of a + * composite purchasable (a bundle) recorded so fulfilment and stock see them; + * the parent holds the money. + */ + public function parent(): BelongsTo + { + return $this->belongsTo(OrderLine::class, 'parent_line_id'); + } + + public function components(): HasMany + { + return $this->hasMany(OrderLine::class, 'parent_line_id')->orderBy('id'); + } + + public function isComponent(): bool + { + return $this->parent_line_id !== null; + } + + /** + * Limit the query to lines that are not components of another line. + */ + public function scopeTopLevel(Builder $query): Builder + { + return $query->whereNull('parent_line_id'); + } + public function fulfilmentLines(): HasMany { return $this->hasMany(FulfilmentLine::class); @@ -112,10 +141,15 @@ public function refundLines(): HasMany /** * Quantity still available to refund — the line's quantity minus - * whatever refund_lines have already claimed against it. + * whatever refund_lines have already claimed against it. Component lines + * carry no money, so they are refunded through their parent. */ public function refundableQuantity(): int { + if ($this->isComponent()) { + return 0; + } + return max(0, $this->quantity - $this->refunded_quantity); } diff --git a/packages/core/src/Models/ProductVariant.php b/packages/core/src/Models/ProductVariant.php index 1cb9692f14..ff13fb8d38 100644 --- a/packages/core/src/Models/ProductVariant.php +++ b/packages/core/src/Models/ProductVariant.php @@ -8,6 +8,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Support\Carbon; use Illuminate\Support\Collection; +use Lunar\Core\Contracts\Actions\Products\ResolvesInventory; use Lunar\Core\Contracts\HasThumbnailImage; use Lunar\Core\Contracts\Purchasable; use Lunar\Core\Contracts\TracksStock; @@ -260,8 +261,7 @@ public function getThumbnail(): ?Media public function canBeFulfilledAtQuantity(int $quantity): bool { - return $this->selling_policy === SellingPolicy::Always - || $quantity <= $this->getTotalInventory(); + return app(ResolvesInventory::class)->execute($this)->allows($quantity); } public function scopeEnabled(Builder $query): Builder @@ -291,11 +291,7 @@ public function hasOrderHistory(): bool public function getTotalInventory(): int { - return match ($this->selling_policy) { - SellingPolicy::Always => $this->stock_available, - SellingPolicy::InStock => $this->stock_available, - SellingPolicy::InStockOrOnBackorder => $this->stock_available + $this->backorder, - }; + return app(ResolvesInventory::class)->execute($this)->available; } public function getThumbnailImage(): string diff --git a/packages/core/src/Observers/OrderLineObserver.php b/packages/core/src/Observers/OrderLineObserver.php index 295fd954fc..add0ad3617 100644 --- a/packages/core/src/Observers/OrderLineObserver.php +++ b/packages/core/src/Observers/OrderLineObserver.php @@ -37,6 +37,15 @@ public function updating(OrderLine $orderLine): void } } + /** + * Component lines go with their parent; done here rather than left to the + * database cascade so model events fire and SQLite test runs match. + */ + public function deleting(OrderLine $orderLine): void + { + $orderLine->components()->get()->each->delete(); + } + /** * Ensure the order line references a purchasable model. */ diff --git a/packages/core/src/Pipelines/Order/Creation/CleanUpOrderLines.php b/packages/core/src/Pipelines/Order/Creation/CleanUpOrderLines.php index 5944639644..c87a95df7d 100644 --- a/packages/core/src/Pipelines/Order/Creation/CleanUpOrderLines.php +++ b/packages/core/src/Pipelines/Order/Creation/CleanUpOrderLines.php @@ -20,7 +20,8 @@ public function handle(Order $order, Closure $next): mixed return $this->signature($line->purchasable_id, $line->purchasable_type, (array) $line->meta, $line->quantity); })->toArray(); - $order->productLines->each(function ($orderLine) use ($cartSignatures) { + // Component lines are never the image of a cart line; they go with their parent. + $order->productLines->whereNull('parent_line_id')->each(function ($orderLine) use ($cartSignatures) { $sig = $this->signature( $orderLine->purchasable_id, $orderLine->purchasable_type, diff --git a/packages/core/src/Pipelines/Order/Creation/CreateOrderLines.php b/packages/core/src/Pipelines/Order/Creation/CreateOrderLines.php index 8cc7036c33..e1a50aa6b0 100644 --- a/packages/core/src/Pipelines/Order/Creation/CreateOrderLines.php +++ b/packages/core/src/Pipelines/Order/Creation/CreateOrderLines.php @@ -26,7 +26,7 @@ public function handle(Order $order, Closure $next): mixed foreach ($cart->lines as $cartLine) { /** @var OrderLine $orderLine */ - $orderLine = $order->lines->first(function ($line) use ($cartLine) { + $orderLine = $order->lines->whereNull('parent_line_id')->first(function ($line) use ($cartLine) { $diff = Arr::diff($line->meta, $cartLine->meta); return empty($diff->new) && diff --git a/packages/core/src/Pipelines/Order/Creation/MapDiscountBreakdown.php b/packages/core/src/Pipelines/Order/Creation/MapDiscountBreakdown.php index dfe6223c2b..02be4c14b8 100644 --- a/packages/core/src/Pipelines/Order/Creation/MapDiscountBreakdown.php +++ b/packages/core/src/Pipelines/Order/Creation/MapDiscountBreakdown.php @@ -18,7 +18,7 @@ public function handle(Order $order, Closure $next): mixed $cartLinesMappedToOrderLines = []; - foreach ($order->lines as $orderLine) { + foreach ($order->lines->whereNull('parent_line_id') as $orderLine) { $cartLine = $cart->lines->first(function ($cartLine) use ($orderLine) { $diff = Arr::diff($cartLine->meta, $orderLine->meta); diff --git a/packages/demo-data/composer.json b/packages/demo-data/composer.json index f3eb571cc3..38384bd25d 100644 --- a/packages/demo-data/composer.json +++ b/packages/demo-data/composer.json @@ -40,5 +40,8 @@ "require": { "php": "^8.4", "lunarphp/core": "self.version" + }, + "suggest": { + "lunarphp/bundles": "Seeds two demo bundles built from the catalogue products." } } diff --git a/packages/demo-data/database/seeders/DemoDataSeeder.php b/packages/demo-data/database/seeders/DemoDataSeeder.php index 143d6b3446..917bfd994e 100644 --- a/packages/demo-data/database/seeders/DemoDataSeeder.php +++ b/packages/demo-data/database/seeders/DemoDataSeeder.php @@ -6,6 +6,7 @@ use Illuminate\Database\Seeder; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; +use Lunar\DemoData\Generators\BundlesGenerator; use Lunar\DemoData\Generators\CatalogueGenerator; use Lunar\DemoData\Generators\CustomersGenerator; use Lunar\DemoData\Generators\FoundationGenerator; @@ -26,6 +27,7 @@ class DemoDataSeeder extends Seeder protected array $generators = [ FoundationGenerator::class, CatalogueGenerator::class, + BundlesGenerator::class, CustomersGenerator::class, OrdersGenerator::class, ]; @@ -49,6 +51,7 @@ class DemoDataSeeder extends Seeder 'collection_customer_group', 'collection_discount', 'brands', 'brand_discount', 'channelables', 'stock_levels', 'stock_movements', 'stock_reservations', + 'bundles', 'bundle_groups', 'bundle_components', ]; public function usingContext(DemoContext $context): static diff --git a/packages/demo-data/src/Generators/BundlesGenerator.php b/packages/demo-data/src/Generators/BundlesGenerator.php new file mode 100644 index 0000000000..600a464a53 --- /dev/null +++ b/packages/demo-data/src/Generators/BundlesGenerator.php @@ -0,0 +1,150 @@ +bound(DefinesBundle::class)) { + return; + } + + $context->reseed(); + + // On a re-run the catalogue generator creates nothing, so fall back to + // the products already in the store (never a bundle's own product). + /** @var Collection $products */ + $products = collect($context->get('products', collect())) + ->whenEmpty(fn () => Product::query() + ->whereHas('variants', fn ($query) => $query + ->whereNotIn('sku', [self::KIT_SKU, self::SET_SKU]) + ->where('stock_available', '>', 0)) + ->orderBy('id') + ->limit(3) + ->get()) + ->filter(fn (Product $product) => $product->variants()->count() > 0) + ->values(); + + $context->set('products', $products); + + if ($products->count() < 3) { + return; + } + + $components = $products->take(3)->map(fn (Product $product) => $product->variants()->first()); + + $this->kit($context, $components); + $this->giftSet($context, $components); + } + + /** + * @param Collection $components + */ + protected function kit(DemoContext $context, Collection $components): void + { + $variant = $this->bundleVariant($context, self::KIT_SKU, 'Essentials Kit', 'Three of our favourites, together at a saving.', 0.0); + + if (! $variant) { + return; + } + + $bundle = app(DefinesBundle::class)->execute($variant, BundlePricing::Components, 10.0); + + $bundle->syncComponents( + $components->values()->map(fn (ProductVariant $component, int $index) => [ + 'variant' => $component, + 'quantity' => 1, + 'position' => $index, + ])->all() + ); + } + + /** + * @param Collection $components + */ + protected function giftSet(DemoContext $context, Collection $components): void + { + $variant = $this->bundleVariant($context, self::SET_SKU, 'Gift Set', 'One of our staples plus your pick of a second.', 60.0); + + if (! $variant) { + return; + } + + $bundle = app(DefinesBundle::class)->execute($variant, BundlePricing::Fixed); + + $bundle->syncGroups([ + ['name' => ['en' => 'Choose your extra'], 'min_selections' => 1, 'max_selections' => 1, 'position' => 0], + ]); + + $group = $bundle->groups()->first(); + + $bundle->syncComponents([ + ['variant' => $components[0], 'quantity' => 1, 'position' => 0], + ['variant' => $components[1], 'quantity' => 1, 'group' => $group, 'default' => true, 'position' => 1], + ['variant' => $components[2], 'quantity' => 1, 'group' => $group, 'position' => 2], + ]); + } + + /** + * Create the bundle's own product and variant, keyed on SKU so a re-run skips it. + */ + protected function bundleVariant(DemoContext $context, string $sku, string $name, string $description, float $price): ?ProductVariant + { + if (ProductVariant::query()->where('sku', $sku)->exists()) { + return null; + } + + $product = Product::create([ + 'product_type_id' => $context->get('products')->first()->product_type_id, + 'status' => 'published', + 'name' => collect(['en' => $name]), + 'description' => collect(['en' => $description]), + 'short_description' => collect(['en' => $description]), + 'attribute_data' => collect(), + ]); + + $product->scheduleChannel($context->get('channel'), now()); + + $variant = ProductVariant::create([ + 'product_id' => $product->id, + 'tax_class_id' => $context->get('taxClass')->id, + 'sku' => $sku, + 'unit_quantity' => 1, + 'shippable' => true, + 'attribute_data' => collect(), + ]); + + // A fixed-price bundle needs its own price rows; a components-priced + // bundle gets them materialised by the package. + if ($price > 0) { + foreach ($context->get('currencies') as $currency) { + $factor = $currency->exchange_rate * (10 ** $currency->decimal_places); + + $variant->prices()->create([ + 'price' => (int) round($price * $factor), + 'currency_id' => $currency->id, + 'min_quantity' => 1, + ]); + } + } + + return $variant; + } +} diff --git a/packages/panel/CLAUDE.md b/packages/panel/CLAUDE.md index 3709455b81..d9411e8212 100644 --- a/packages/panel/CLAUDE.md +++ b/packages/panel/CLAUDE.md @@ -32,7 +32,7 @@ public page-building surface to them: `app.ts` publishes the components on `@lunarphp/panel` import to that global. **`resources/js/ui.ts` is the source of truth for what add-ons can import** — the barrel there lists the whole set (layout, DataTable, FilterDropdown, KpiCard, form inputs, overlays, `Button`, `Icon`, …). -Internal machinery (`NavBody`, `PanelSlot`, `RowActions`, `PageActions`, `Section`, …) +Internal machinery (`NavBody`, `PanelSlot`, `RowActions`, `PageActions`, …) is deliberately not exported. The `PanelLayout` shell is applied to add-on pages automatically (the resolver sets it as their persistent layout via the `default` entry in the layout registry), so an add-on page only builds its own `PageHeader` + diff --git a/packages/panel/public/build/assets/app-C3gs_Or0.js b/packages/panel/public/build/assets/app-C3gs_Or0.js deleted file mode 100644 index ff81bdd4a7..0000000000 --- a/packages/panel/public/build/assets/app-C3gs_Or0.js +++ /dev/null @@ -1,272 +0,0 @@ -var lP=Object.defineProperty;var e_=e=>{throw TypeError(e)};var iP=(e,t,n)=>t in e?lP(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Re=(e,t,n)=>iP(e,typeof t!="symbol"?t+"":t,n),aP=(e,t,n)=>t.has(e)||e_("Cannot "+n);var Ha=(e,t,n)=>(aP(e,t,"read from private field"),n?n.call(e):t.get(e)),za=(e,t,n)=>t.has(e)?e_("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n);/* empty css *//** -* @vue/shared v3.5.42 -* (c) 2018-present Yuxi (Evan) You and Vue contributors -* @license MIT -**/function nm(e){const t=Object.create(null);for(const n of e.split(","))t[n]=1;return n=>n in t}const bt={},Hi=[],qr=()=>{},Sw=()=>!1,Pc=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),rm=e=>e.startsWith("onUpdate:"),Nt=Object.assign,Ay=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},uP=Object.prototype.hasOwnProperty,Ot=(e,t)=>uP.call(e,t),Ke=Array.isArray,Jo=e=>Pa(e)==="[object Map]",Es=e=>Pa(e)==="[object Set]",t_=e=>Pa(e)==="[object Date]",cP=e=>Pa(e)==="[object RegExp]",nt=e=>typeof e=="function",jt=e=>typeof e=="string",wr=e=>typeof e=="symbol",Pt=e=>e!==null&&typeof e=="object",Py=e=>(Pt(e)||nt(e))&&nt(e.then)&&nt(e.catch),Ew=Object.prototype.toString,Pa=e=>Ew.call(e),dP=e=>Pa(e).slice(8,-1),sm=e=>Pa(e)==="[object Object]",om=e=>jt(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Ul=nm(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),lm=e=>{const t=Object.create(null);return(n=>t[n]||(t[n]=e(n)))},fP=/-\w/g,fn=lm(e=>e.replace(fP,t=>t.slice(1).toUpperCase())),pP=/\B([A-Z])/g,dr=lm(e=>e.replace(pP,"-$1").toLowerCase()),Mc=lm(e=>e.charAt(0).toUpperCase()+e.slice(1)),zi=lm(e=>e?`on${Mc(e)}`:""),On=(e,t)=>!Object.is(e,t),Ki=(e,...t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:r,value:n})},im=e=>{const t=parseFloat(e);return isNaN(t)?e:t},vf=e=>{const t=jt(e)?Number(e):NaN;return isNaN(t)?e:t};let n_;const am=()=>n_||(n_=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{}),mP="Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console,Error,Symbol",hP=nm(mP);function kt(e){if(Ke(e)){const t={};for(let n=0;n{if(n){const r=n.split(vP);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t}function pe(e){let t="";if(jt(e))t=e;else if(Ke(e))for(let n=0;nKr(n,t))}const Aw=e=>!!(e&&e.__v_isRef===!0),m=e=>jt(e)?e:e==null?"":Ke(e)||Pt(e)&&(e.toString===Ew||!nt(e.toString))?Aw(e)?m(e.value):JSON.stringify(e,Pw,2):String(e),Pw=(e,t)=>Aw(t)?Pw(e,t.value):Jo(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[r,s],o)=>(n[yh(r,o)+" =>"]=s,n),{})}:Es(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>yh(n))}:wr(t)?yh(t):Pt(t)&&!Ke(t)&&!sm(t)?String(t):t,yh=(e,t="")=>{var n;return wr(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};function wP(e){return e==null?"initial":typeof e=="string"?e===""?" ":e:String(e)}/** -* @vue/reactivity v3.5.42 -* (c) 2018-present Yuxi (Evan) You and Vue contributors -* @license MIT -**/let Cn;class My{constructor(t=!1){this.detached=t,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this._warnOnRun=!0,this.__v_skip=!0,!t&&Cn&&(Cn.active?(this.parent=Cn,this.index=(Cn.scopes||(Cn.scopes=[])).push(this)-1):(this._active=!1,this._warnOnRun=!1))}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,n;if(this.scopes){const r=this.scopes.slice();for(t=0,n=r.length;t0&&--this._on===0){if(Cn===this)Cn=this.prevScope;else{let t=Cn;for(;t;){if(t.prevScope===this){t.prevScope=this.prevScope;break}t=t.prevScope}}this.prevScope=void 0}}stop(t){if(this._active){this._active=!1;let n,r;for(n=0,r=this.effects.length;n0)return;if(wu){let t=wu;for(wu=void 0;t;){const n=t.next;t.next=void 0,t.flags&=-9,t=n}}let e;for(;ku;){let t=ku;for(ku=void 0;t;){const n=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(r){e||(e=r)}t=n}}if(e)throw e}function Vw(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function Iw(e){let t,n=e.depsTail,r=n;for(;r;){const s=r.prevDep;r.version===-1?(r===n&&(n=s),Iy(r),$P(r)):t=r,r.dep.activeLink=r.prevActiveLink,r.prevActiveLink=void 0,r=s}e.deps=t,e.depsTail=n}function zg(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(Rw(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function Rw(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===Gu)||(e.globalVersion=Gu,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!zg(e))))return;e.flags|=2;const t=e.dep,n=Kt,r=es;Kt=e,es=!0;try{Vw(e);const s=e.fn(e._value);(t.version===0||On(s,e._value))&&(e.flags|=128,e._value=s,t.version++)}catch(s){throw t.version++,s}finally{Kt=n,es=r,Iw(e),e.flags&=-3}}function Iy(e,t=!1){const{dep:n,prevSub:r,nextSub:s}=e;if(r&&(r.nextSub=s,e.prevSub=void 0),s&&(s.prevSub=r,e.nextSub=void 0),n.subs===e&&(n.subs=r,!r&&n.computed)){n.computed.flags&=-5;for(let o=n.computed.deps;o;o=o.nextDep)Iy(o,!0)}!t&&!--n.sc&&n.map&&n.map.delete(n.key)}function $P(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}function CP(e,t){e.effect instanceof Wu&&(e=e.effect.fn);const n=new Wu(e);t&&Nt(n,t);try{n.run()}catch(s){throw n.stop(),s}const r=n.run.bind(n);return r.effect=n,r}function SP(e){e.effect.stop()}let es=!0;const Nw=[];function ao(){Nw.push(es),es=!1}function uo(){const e=Nw.pop();es=e===void 0?!0:e}function s_(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const n=Kt;Kt=void 0;try{t()}finally{Kt=n}}}let Gu=0,EP=class{constructor(t,n){this.sub=t,this.dep=n,this.version=n.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}};class dm{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!Kt||!es||Kt===this.computed)return;let n=this.activeLink;if(n===void 0||n.sub!==Kt)n=this.activeLink=new EP(Kt,this),Kt.deps?(n.prevDep=Kt.depsTail,Kt.depsTail.nextDep=n,Kt.depsTail=n):Kt.deps=Kt.depsTail=n,Lw(n);else if(n.version===-1&&(n.version=this.version,n.nextDep)){const r=n.nextDep;r.prevDep=n.prevDep,n.prevDep&&(n.prevDep.nextDep=r),n.prevDep=Kt.depsTail,n.nextDep=void 0,Kt.depsTail.nextDep=n,Kt.depsTail=n,Kt.deps===n&&(Kt.deps=r)}return n}trigger(t){this.version++,Gu++,this.notify(t)}notify(t){Dy();try{for(let n=this.subs;n;n=n.prevSub)n.sub.notify()&&n.sub.dep.notify()}finally{Vy()}}}function Lw(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let r=t.deps;r;r=r.nextDep)Lw(r)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}const yf=new WeakMap,jl=Symbol(""),Kg=Symbol(""),Ju=Symbol("");function qn(e,t,n){if(es&&Kt){let r=yf.get(e);r||yf.set(e,r=new Map);let s=r.get(n);s||(r.set(n,s=new dm),s.map=r,s.key=n),s.track()}}function Hs(e,t,n,r,s,o){const l=yf.get(e);if(!l){Gu++;return}const a=u=>{u&&u.trigger()};if(Dy(),t==="clear")l.forEach(a);else{const u=Ke(e),c=u&&om(n);if(u&&n==="length"){const d=Number(r);l.forEach((f,p)=>{(p==="length"||p===Ju||!wr(p)&&p>=d)&&a(f)})}else switch((n!==void 0||l.has(void 0))&&a(l.get(n)),c&&a(l.get(Ju)),t){case"add":u?c&&a(l.get("length")):(a(l.get(jl)),Jo(e)&&a(l.get(Kg)));break;case"delete":u||(a(l.get(jl)),Jo(e)&&a(l.get(Kg)));break;case"set":Jo(e)&&a(l.get(jl));break}}Vy()}function OP(e,t){const n=yf.get(e);return n&&n.get(t)}function _i(e){const t=$t(e);return t===e?t:(qn(t,"iterate",Ju),mr(e)?t:t.map(rs))}function fm(e){return qn(e=$t(e),"iterate",Ju),e}function ks(e,t){return Os(e)?oa(Cs(e)?rs(t):t):rs(t)}const TP={__proto__:null,[Symbol.iterator](){return _h(this,Symbol.iterator,e=>ks(this,e))},concat(...e){return _i(this).concat(...e.map(t=>Ke(t)?_i(t):t))},entries(){return _h(this,"entries",e=>(e[1]=ks(this,e[1]),e))},every(e,t){return Ds(this,"every",e,t,void 0,arguments)},filter(e,t){return Ds(this,"filter",e,t,n=>n.map(r=>ks(this,r)),arguments)},find(e,t){return Ds(this,"find",e,t,n=>ks(this,n),arguments)},findIndex(e,t){return Ds(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return Ds(this,"findLast",e,t,n=>ks(this,n),arguments)},findLastIndex(e,t){return Ds(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return Ds(this,"forEach",e,t,void 0,arguments)},includes(...e){return xh(this,"includes",e)},indexOf(...e){return xh(this,"indexOf",e)},join(e){return _i(this).join(e)},lastIndexOf(...e){return xh(this,"lastIndexOf",e)},map(e,t){return Ds(this,"map",e,t,void 0,arguments)},pop(){return Ka(this,"pop")},push(...e){return Ka(this,"push",e)},reduce(e,...t){return o_(this,"reduce",e,t)},reduceRight(e,...t){return o_(this,"reduceRight",e,t)},shift(){return Ka(this,"shift")},some(e,t){return Ds(this,"some",e,t,void 0,arguments)},splice(...e){return Ka(this,"splice",e)},toReversed(){return _i(this).toReversed()},toSorted(e){return _i(this).toSorted(e)},toSpliced(...e){return _i(this).toSpliced(...e)},unshift(...e){return Ka(this,"unshift",e)},values(){return _h(this,"values",e=>ks(this,e))}};function _h(e,t,n){const r=fm(e),s=r[t]();return r!==e&&!mr(e)&&(s._next=s.next,s.next=()=>{const o=s._next();return o.done||(o.value=n(o.value)),o}),s}const AP=Array.prototype;function Ds(e,t,n,r,s,o){const l=fm(e),a=l!==e&&!mr(e),u=l[t];if(u!==AP[t]){const f=u.apply(e,o);return a?rs(f):f}let c=n;l!==e&&(a?c=function(f,p){return n.call(this,ks(e,f),p,e)}:n.length>2&&(c=function(f,p){return n.call(this,f,p,e)}));const d=u.call(l,c,r);return a&&s?s(d):d}function o_(e,t,n,r){const s=fm(e),o=s!==e&&!mr(e);let l=n,a=!1;s!==e&&(o?(a=r.length===0,l=function(c,d,f){return a&&(a=!1,c=ks(e,c)),n.call(this,c,ks(e,d),f,e)}):n.length>3&&(l=function(c,d,f){return n.call(this,c,d,f,e)}));const u=s[t](l,...r);return a?ks(e,u):u}function xh(e,t,n){const r=$t(e);qn(r,"iterate",Ju);const s=r[t](...n);return(s===-1||s===!1)&&Vc(n[0])?(n[0]=$t(n[0]),r[t](...n)):s}function Ka(e,t,n=[]){ao(),Dy();const r=$t(e)[t].apply(e,n);return Vy(),uo(),r}const PP=nm("__proto__,__v_isRef,__isVue"),Fw=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(wr));function MP(e){wr(e)||(e=String(e));const t=$t(this);return qn(t,"has",e),t.hasOwnProperty(e)}class Bw{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,r){if(n==="__v_skip")return t.__v_skip;const s=this._isReadonly,o=this._isShallow;if(n==="__v_isReactive")return!s;if(n==="__v_isReadonly")return s;if(n==="__v_isShallow")return o;if(n==="__v_raw")return r===(s?o?Kw:zw:o?Hw:jw).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(r)?t:void 0;const l=Ke(t);if(!s){let u;if(l&&(u=TP[n]))return u;if(n==="hasOwnProperty")return MP}const a=Reflect.get(t,n,Et(t)?t:r);if((wr(n)?Fw.has(n):PP(n))||(s||qn(t,"get",n),o))return a;if(Et(a)){const u=l&&om(n)?a:a.value;return s&&Pt(u)?bf(u):u}return Pt(a)?s?bf(a):rt(a):a}}class qw extends Bw{constructor(t=!1){super(!1,t)}set(t,n,r,s){let o=t[n];const l=Ke(t)&&om(n);if(!this._isShallow){const c=Os(o);if(!mr(r)&&!Os(r)&&(o=$t(o),r=$t(r)),!l&&Et(o)&&!Et(r))return c||(o.value=r),!0}const a=l?Number(n)e,dd=e=>Reflect.getPrototypeOf(e);function NP(e,t,n){return function(...r){const s=this.__v_raw,o=$t(s),l=Jo(o),a=e==="entries"||e===Symbol.iterator&&l,u=e==="keys"&&l,c=s[e](...r),d=n?Wg:t?oa:rs;return!t&&qn(o,"iterate",u?Kg:jl),Nt(Object.create(c),{next(){const{value:f,done:p}=c.next();return p?{value:f,done:p}:{value:a?[d(f[0]),d(f[1])]:d(f),done:p}}})}}function fd(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function LP(e,t){const n={get(s){const o=this.__v_raw,l=$t(o),a=$t(s);e||(On(s,a)&&qn(l,"get",s),qn(l,"get",a));const{has:u}=dd(l),c=t?Wg:e?oa:rs;if(u.call(l,s))return c(o.get(s));if(u.call(l,a))return c(o.get(a));o!==l&&o.get(s)},get size(){const s=this.__v_raw;return!e&&qn($t(s),"iterate",jl),s.size},has(s){const o=this.__v_raw,l=$t(o),a=$t(s);return e||(On(s,a)&&qn(l,"has",s),qn(l,"has",a)),s===a?o.has(s):o.has(s)||o.has(a)},forEach(s,o){const l=this,a=l.__v_raw,u=$t(a),c=t?Wg:e?oa:rs;return!e&&qn(u,"iterate",jl),a.forEach((d,f)=>s.call(o,c(d),c(f),l))}};return Nt(n,e?{add:fd("add"),set:fd("set"),delete:fd("delete"),clear:fd("clear")}:{add(s){const o=$t(this),l=dd(o),a=$t(s),u=!t&&!mr(s)&&!Os(s)?a:s;return l.has.call(o,u)||On(s,u)&&l.has.call(o,s)||On(a,u)&&l.has.call(o,a)||(o.add(u),Hs(o,"add",u,u)),this},set(s,o){!t&&!mr(o)&&!Os(o)&&(o=$t(o));const l=$t(this),{has:a,get:u}=dd(l);let c=a.call(l,s);c||(s=$t(s),c=a.call(l,s));const d=u.call(l,s);return l.set(s,o),c?On(o,d)&&Hs(l,"set",s,o):Hs(l,"add",s,o),this},delete(s){const o=$t(this),{has:l,get:a}=dd(o);let u=l.call(o,s);u||(s=$t(s),u=l.call(o,s)),a&&a.call(o,s);const c=o.delete(s);return u&&Hs(o,"delete",s,void 0),c},clear(){const s=$t(this),o=s.size!==0,l=s.clear();return o&&Hs(s,"clear",void 0,void 0),l}}),["keys","values","entries",Symbol.iterator].forEach(s=>{n[s]=NP(s,e,t)}),n}function pm(e,t){const n=LP(e,t);return(r,s,o)=>s==="__v_isReactive"?!e:s==="__v_isReadonly"?e:s==="__v_raw"?r:Reflect.get(Ot(n,s)&&s in r?n:r,s,o)}const FP={get:pm(!1,!1)},BP={get:pm(!1,!0)},qP={get:pm(!0,!1)},UP={get:pm(!0,!0)},jw=new WeakMap,Hw=new WeakMap,zw=new WeakMap,Kw=new WeakMap;function jP(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function rt(e){return Os(e)?e:mm(e,!1,DP,FP,jw)}function Ww(e){return mm(e,!1,IP,BP,Hw)}function bf(e){return mm(e,!0,VP,qP,zw)}function Ro(e){return mm(e,!0,RP,UP,Kw)}function mm(e,t,n,r,s){if(!Pt(e)||e.__v_raw&&!(t&&e.__v_isReactive)||e.__v_skip||!Object.isExtensible(e))return e;const o=s.get(e);if(o)return o;const l=jP(dP(e));if(l===0)return e;const a=new Proxy(e,l===2?r:n);return s.set(e,a),a}function Cs(e){return Os(e)?Cs(e.__v_raw):!!(e&&e.__v_isReactive)}function Os(e){return!!(e&&e.__v_isReadonly)}function mr(e){return!!(e&&e.__v_isShallow)}function Vc(e){return e?!!e.__v_raw:!1}function $t(e){const t=e&&e.__v_raw;return t?$t(t):e}function sa(e){return!Ot(e,"__v_skip")&&Object.isExtensible(e)&&Ow(e,"__v_skip",!0),e}const rs=e=>Pt(e)?rt(e):e,oa=e=>Pt(e)?bf(e):e;function Et(e){return e?e.__v_isRef===!0:!1}function U(e){return Gw(e,!1)}function yo(e){return Gw(e,!0)}function Gw(e,t){return Et(e)?e:new HP(e,t)}class HP{constructor(t,n){this.dep=new dm,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=n?t:$t(t),this._value=n?t:rs(t),this.__v_isShallow=n}get value(){return this.dep.track(),this._value}set value(t){const n=this._rawValue,r=this.__v_isShallow||mr(t)||Os(t);t=r?t:$t(t),On(t,n)&&(this._rawValue=t,this._value=r?t:rs(t),this.dep.trigger())}}function Jw(e){e.dep&&e.dep.trigger()}function i(e){return Et(e)?e.value:e}function Ln(e){return nt(e)?e():i(e)}const zP={get:(e,t,n)=>t==="__v_raw"?e:i(Reflect.get(e,t,n)),set:(e,t,n,r)=>{const s=e[t];return Et(s)&&!Et(n)?(s.value=n,!0):Reflect.set(e,t,n,r)}};function Ry(e){return Cs(e)?e:new Proxy(e,zP)}class KP{constructor(t){this.__v_isRef=!0,this._value=void 0;const n=this.dep=new dm,{get:r,set:s}=t(n.track.bind(n),n.trigger.bind(n));this._get=r,this._set=s}get value(){return this._value=this._get()}set value(t){this._set(t)}}function hm(e){return new KP(e)}function ln(e){const t=Ke(e)?new Array(e.length):{};for(const n in e)t[n]=Xw(e,n);return t}class WP{constructor(t,n,r){this._object=t,this._defaultValue=r,this.__v_isRef=!0,this._value=void 0,this._key=wr(n)?n:String(n),this._raw=$t(t);let s=!0,o=t;if(!Ke(t)||wr(this._key)||!om(this._key))do s=!Vc(o)||mr(o);while(s&&(o=o.__v_raw));this._shallow=s}get value(){let t=this._object[this._key];return this._shallow&&(t=i(t)),this._value=t===void 0?this._defaultValue:t}set value(t){if(this._shallow&&Et(this._raw[this._key])){const n=this._object[this._key];if(Et(n)){n.value=t;return}}this._object[this._key]=t}get dep(){return OP(this._raw,this._key)}}class GP{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0,this._value=void 0}get value(){return this._value=this._getter()}}function Yw(e,t,n){return Et(e)?e:nt(e)?new GP(e):Pt(e)&&arguments.length>1?Xw(e,t,n):U(e)}function Xw(e,t,n){return new WP(e,t,n)}class JP{constructor(t,n,r){this.fn=t,this.setter=n,this._value=void 0,this.dep=new dm(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=Gu-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!n,this.isSSR=r}notify(){if(this.flags|=16,!(this.flags&8)&&Kt!==this)return Dw(this,!0),!0}get value(){const t=this.dep.track();return Rw(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function YP(e,t,n=!1){let r,s;return nt(e)?r=e:(r=e.get,s=e.set),new JP(r,s,n)}const XP={GET:"get",HAS:"has",ITERATE:"iterate"},QP={SET:"set",ADD:"add",DELETE:"delete",CLEAR:"clear"},pd={},_f=new WeakMap;let No;function ZP(){return No}function Qw(e,t=!1,n=No){if(n){let r=_f.get(n);r||_f.set(n,r=[]),r.push(e)}}function e5(e,t,n=bt){const{immediate:r,deep:s,once:o,scheduler:l,augmentJob:a,call:u}=n,c=E=>s?E:mr(E)||s===!1||s===0?zs(E,1):zs(E);let d,f,p,h,b=!1,x=!1;if(Et(e)?(f=()=>e.value,b=mr(e)):Cs(e)?(f=()=>c(e),b=!0):Ke(e)?(x=!0,b=e.some(E=>Cs(E)||mr(E)),f=()=>e.map(E=>{if(Et(E))return E.value;if(Cs(E))return c(E);if(nt(E))return u?u(E,2):E()})):nt(e)?t?f=u?()=>u(e,2):e:f=()=>{if(p){ao();try{p()}finally{uo()}}const E=No;No=d;try{return u?u(e,3,[h]):e(h)}finally{No=E}}:f=qr,t&&s){const E=f,T=s===!0?1/0:s;f=()=>zs(E(),T)}const w=Ma(),k=()=>{d.stop(),w&&w.active&&Ay(w.effects,d)};if(o&&t){const E=t;t=(...T)=>{const O=E(...T);return k(),O}}let C=x?new Array(e.length).fill(pd):pd;const S=E=>{if(!(!(d.flags&1)||!d.dirty&&!E))if(t){const T=d.run();if(E||s||b||(x?T.some((O,P)=>On(O,C[P])):On(T,C))){p&&p();const O=No;No=d;try{const P=[T,C===pd?void 0:x&&C[0]===pd?[]:C,h];C=T,u?u(t,3,P):t(...P)}finally{No=O}}}else d.run()};return a&&a(S),d=new Wu(f),d.scheduler=l?()=>l(S,!1):S,h=E=>Qw(E,!1,d),p=d.onStop=()=>{const E=_f.get(d);if(E){if(u)u(E,4);else for(const T of E)T();_f.delete(d)}},t?r?S(!0):C=d.run():l?l(S.bind(null,!0),!0):d.run(),k.pause=d.pause.bind(d),k.resume=d.resume.bind(d),k.stop=k,k}function zs(e,t=1/0,n){if(t<=0||!Pt(e)||e.__v_skip||(n=n||new Map,(n.get(e)||0)>=t))return e;if(n.set(e,t),t--,Et(e))zs(e.value,t,n);else if(Ke(e))for(let r=0;r{zs(r,t,n)});else if(sm(e)){for(const r in e)zs(e[r],t,n);for(const r of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,r)&&zs(e[r],t,n)}return e}/** -* @vue/runtime-core v3.5.42 -* (c) 2018-present Yuxi (Evan) You and Vue contributors -* @license MIT -**/const Zw=[];function t5(e){Zw.push(e)}function n5(){Zw.pop()}function r5(e,t){}const s5={SETUP_FUNCTION:0,0:"SETUP_FUNCTION",RENDER_FUNCTION:1,1:"RENDER_FUNCTION",NATIVE_EVENT_HANDLER:5,5:"NATIVE_EVENT_HANDLER",COMPONENT_EVENT_HANDLER:6,6:"COMPONENT_EVENT_HANDLER",VNODE_HOOK:7,7:"VNODE_HOOK",DIRECTIVE_HOOK:8,8:"DIRECTIVE_HOOK",TRANSITION_HOOK:9,9:"TRANSITION_HOOK",APP_ERROR_HANDLER:10,10:"APP_ERROR_HANDLER",APP_WARN_HANDLER:11,11:"APP_WARN_HANDLER",FUNCTION_REF:12,12:"FUNCTION_REF",ASYNC_COMPONENT_LOADER:13,13:"ASYNC_COMPONENT_LOADER",SCHEDULER:14,14:"SCHEDULER",COMPONENT_UPDATE:15,15:"COMPONENT_UPDATE",APP_UNMOUNT_CLEANUP:16,16:"APP_UNMOUNT_CLEANUP"},o5={sp:"serverPrefetch hook",bc:"beforeCreate hook",c:"created hook",bm:"beforeMount hook",m:"mounted hook",bu:"beforeUpdate hook",u:"updated",bum:"beforeUnmount hook",um:"unmounted hook",a:"activated hook",da:"deactivated hook",ec:"errorCaptured hook",rtc:"renderTracked hook",rtg:"renderTriggered hook",0:"setup function",1:"render function",2:"watcher getter",3:"watcher callback",4:"watcher cleanup function",5:"native event handler",6:"component event handler",7:"vnode hook",8:"directive hook",9:"transition hook",10:"app errorHandler",11:"app warnHandler",12:"ref function",13:"async component loader",14:"scheduler flush",15:"component update",16:"app unmount cleanup function"};function Da(e,t,n,r){try{return r?e(...r):e()}catch(s){fi(s,t,n)}}function $r(e,t,n,r){if(nt(e)){const s=Da(e,t,n,r);return s&&Py(s)&&s.catch(o=>{fi(o,t,n)}),s}if(Ke(e)){const s=[];for(let o=0;o>>1,s=Xn[r],o=Xu(s);o=Xu(n)?Xn.push(e):Xn.splice(i5(t),0,e),e.flags|=1,t2()}}function t2(){xf||(xf=e2.then(n2))}function Yu(e){if(!Ke(e))Lo&&e.id===-1?Lo.splice(Ai+1,0,e):e.flags&1||(Wi.push(e),e.flags|=1);else for(let t=0;tXu(n)-Xu(r));if(Wi.length=0,Lo){for(let n=0;ne.id==null?e.flags&2?-1:1/0:e.id;function n2(e){try{for(ms=0;msPi.emit(s,...o)),md=[]):typeof window<"u"&&window.HTMLElement&&!((r=(n=window.navigator)==null?void 0:n.userAgent)!=null&&r.includes("jsdom"))?((t.__VUE_DEVTOOLS_HOOK_REPLAY__=t.__VUE_DEVTOOLS_HOOK_REPLAY__||[]).push(o=>{r2(o,t)}),setTimeout(()=>{Pi||(t.__VUE_DEVTOOLS_HOOK_REPLAY__=null,md=[])},3e3)):md=[]}let Rn=null,gm=null;function Qu(e){const t=Rn;return Rn=e,gm=e&&e.type.__scopeId||null,t}function a5(e){gm=e}function u5(){gm=null}const c5=e=>_;function _(e,t=Rn,n){if(!t||e._n)return e;const r=(...s)=>{r._d&&tc(-1);const o=Qu(t),l=ro.length;let a;try{a=e(...s)}finally{for(let u=ro.length;u>l;u--)Cm();Qu(o),r._d&&tc(1)}return a};return r._n=!0,r._c=!0,r._d=!0,r}function jn(e,t){if(Rn===null)return e;const n=Fc(Rn),r=e.dirs||(e.dirs=[]);for(let s=0;s1)return n&&nt(t)?t.call(r&&r.proxy):t}}function d5(){return!!(zt()||Hl)}const s2=Symbol.for("v-scx"),o2=()=>eo(s2);function Cr(e,t){return Rc(e,null,t)}function Ly(e,t){return Rc(e,null,{flush:"post"})}function Fy(e,t){return Rc(e,null,{flush:"sync"})}function ye(e,t,n){return Rc(e,t,n)}function Rc(e,t,n=bt){const{immediate:r,deep:s,flush:o,once:l}=n,a=Nt({},n),u=t&&r||!t&&o!=="post";let c;if(Zl){if(o==="sync"){const h=o2();c=h.__watcherHandles||(h.__watcherHandles=[])}else if(!u){const h=()=>{};return h.stop=qr,h.resume=qr,h.pause=qr,h}}const d=In;a.call=(h,b,x)=>$r(h,d,b,x);let f=!1;o==="post"?a.scheduler=h=>{bn(h,d&&d.suspense)}:o!=="sync"&&(f=!0,a.scheduler=(h,b)=>{b?h():Ny(h)}),a.augmentJob=h=>{t&&(h.flags|=4),f&&(h.flags|=2,d&&(h.id=d.uid,h.i=d))};const p=e5(e,t,a);return Zl&&(c?c.push(p):u&&p()),p}function f5(e,t,n){const r=this.proxy,s=jt(e)?e.includes(".")?l2(r,e):()=>r[e]:e.bind(r,r);let o;nt(t)?o=t:(o=t.handler,n=t);const l=Va(this),a=Rc(s,o.bind(r),n);return l(),a}function l2(e,t){const n=t.split(".");return()=>{let r=e;for(let s=0;se.__isTeleport,Pl=e=>e&&(e.disabled||e.disabled===""),p5=e=>e&&(e.defer||e.defer===""),i_=e=>typeof SVGElement<"u"&&e instanceof SVGElement,a_=e=>typeof MathMLElement=="function"&&e instanceof MathMLElement,Gg=(e,t)=>{const n=e&&e.to;return jt(n)?t?t(n):null:n},m5={name:"Teleport",__isTeleport:!0,process(e,t,n,r,s,o,l,a,u,c){const{mc:d,pc:f,pbc:p,o:{insert:h,querySelector:b,createText:x,createComment:w,parentNode:k}}=c,C=Pl(t.props);let{dynamicChildren:S}=t;const E=(P,I,M)=>{P.shapeFlag&16&&d(P.children,I,M,s,o,l,a,u)},T=(P=t)=>{const I=Pl(P.props),M=P.target=Gg(P.props,b),D=Jg(M,P,x,h);M&&(l!=="svg"&&i_(M)?l="svg":l!=="mathml"&&a_(M)&&(l="mathml"),s&&s.isCE&&(s.ce._teleportTargets||(s.ce._teleportTargets=new Set)).add(M),I||(E(P,M,D),cu(P,!1)))},O=P=>{const I=()=>{if(Po.get(P)===I){if(Po.delete(P),Pl(P.props)){const M=k(P.el)||n;E(P,M,P.anchor),cu(P,!0)}T(P)}};Po.set(P,I),bn(I,o)};if(e==null){const P=t.el=x(""),I=t.anchor=x("");if(h(P,n,r),h(I,n,r),p5(t.props)||o&&o.pendingBranch){O(t);return}C&&(E(t,n,I),cu(t,!0)),T()}else{t.el=e.el;const P=t.anchor=e.anchor,I=Po.get(e);if(I){I.flags|=8,Po.delete(e),O(t);return}t.targetStart=e.targetStart;const M=t.target=e.target,D=t.targetAnchor=e.targetAnchor,L=Pl(e.props),F=L?n:M,N=L?P:D;if(l==="svg"||i_(M)?l="svg":(l==="mathml"||a_(M))&&(l="mathml"),S?(p(e.dynamicChildren,S,F,s,o,l,a),e1(e,t,!0)):u||f(e,t,F,N,s,o,l,a,!1),C)L?t.props&&e.props&&t.props.to!==e.props.to&&(t.props.to=e.props.to):hd(t,n,P,c,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const j=Gg(t.props,b);j&&(t.target=j,hd(t,j,null,c,0))}else L&&hd(t,M,D,c,1);cu(t,C)}},remove(e,t,n,{um:r,o:{remove:s}},o){const{shapeFlag:l,children:a,anchor:u,targetStart:c,targetAnchor:d,target:f,props:p}=e,h=Pl(p),b=o||!h,x=Po.get(e);if(x&&(x.flags|=8,Po.delete(e)),f&&(s(c),s(d)),o&&s(u),!x&&(h||f)&&l&16)for(let w=0;w{e.isMounted=!0}),Kn(()=>{e.isUnmounting=!0}),e}const Or=[Function,Array],Uy={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Or,onEnter:Or,onAfterEnter:Or,onEnterCancelled:Or,onBeforeLeave:Or,onLeave:Or,onAfterLeave:Or,onLeaveCancelled:Or,onBeforeAppear:Or,onAppear:Or,onAfterAppear:Or,onAppearCancelled:Or},a2=e=>{const t=e.subTree;return t.component?a2(t.component):t},g5={name:"BaseTransition",props:Uy,setup(e,{slots:t}){const n=zt(),r=qy();return()=>{const s=t.default&&ym(t.default(),!0),o=s&&s.length?u2(s):n.subTree?R():void 0;if(!o)return;const l=$t(e),{mode:a}=l;if(r.isLeaving)return kh(o);const u=wf(o);if(!u)return kh(o);let c=la(u,l,r,n,f=>c=f);u.type!==dn&&co(u,c);let d=n.subTree&&wf(n.subTree);if(d&&d.type!==dn&&!Yr(d,u)&&a2(n).type!==dn){let f=la(d,l,r,n);if(co(d,f),a==="out-in"&&u.type!==dn)return r.isLeaving=!0,f.afterLeave=()=>{r.isLeaving=!1,n.job.flags&8||n.update(),delete f.afterLeave,d=void 0},kh(o);a==="in-out"&&u.type!==dn?f.delayLeave=(p,h,b)=>{const x=d2(r,d);x[String(d.key)]=d,p[Dr]=()=>{h(),p[Dr]=void 0,delete c.delayedLeave,d=void 0},c.delayedLeave=()=>{b(),delete c.delayedLeave,d=void 0}}:d=void 0}else d&&(d=void 0);return o}}};function u2(e){let t=e[0];if(e.length>1){for(const n of e)if(n.type!==dn){t=n;break}}return t}const c2=g5;function d2(e,t){const{leavingVNodes:n}=e;let r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function la(e,t,n,r,s){const{appear:o,mode:l,persisted:a=!1,onBeforeEnter:u,onEnter:c,onAfterEnter:d,onEnterCancelled:f,onBeforeLeave:p,onLeave:h,onAfterLeave:b,onLeaveCancelled:x,onBeforeAppear:w,onAppear:k,onAfterAppear:C,onAppearCancelled:S}=t,E=String(e.key),T=d2(n,e),O=(M,D)=>{M&&$r(M,r,9,D)},P=(M,D)=>{const L=D[1];O(M,D),Ke(M)?M.every(F=>F.length<=1)&&L():M.length<=1&&L()},I={mode:l,persisted:a,beforeEnter(M){let D=u;if(!n.isMounted)if(o)D=w||u;else return;M[Dr]&&M[Dr](!0);const L=T[E];L&&Yr(e,L)&&L.el[Dr]&&L.el[Dr](),O(D,[M])},enter(M){if(T[E]===e)return;let D=c,L=d,F=f;if(!n.isMounted)if(o)D=k||c,L=C||d,F=S||f;else return;let N=!1;M[Wa]=q=>{N||(N=!0,q?O(F,[M]):O(L,[M]),I.delayedLeave&&I.delayedLeave(),M[Wa]=void 0)};const j=M[Wa].bind(null,!1);D?P(D,[M,j]):j()},leave(M,D){const L=String(e.key);if(M[Wa]&&M[Wa](!0),n.isUnmounting)return D();O(p,[M]);let F=!1;M[Dr]=j=>{F||(F=!0,D(),j?O(x,[M]):O(b,[M]),M[Dr]=void 0,T[L]===e&&delete T[L])};const N=M[Dr].bind(null,!1);T[L]=e,h?P(h,[M,N]):N()},clone(M){const D=la(M,t,n,r,s);return s&&s(D),D}};return I}function kh(e){if(Nc(e))return e=ss(e),e.children=null,e}function wf(e){if(!Nc(e))return vm(e.type)&&e.children?u2(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:n}=e;if(n){if(t&16)return n[0];if(t&32&&nt(n.default))return n.default()}}function co(e,t){if(e.shapeFlag&6&&e.component){e.transition=t;const n=e.component.subTree;co(vm(n.type)&&wf(n)||n,t)}else e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function ym(e,t=!1,n){let r=[],s=0;for(let o=0;o1)for(let o=0;on.value,set:o=>n.value=o})}return n}function u_(e,t){let n;return!!((n=Object.getOwnPropertyDescriptor(e,t))&&!n.configurable)}const $f=new WeakMap;function Gi(e,t,n,r,s=!1){if(Ke(e)){e.forEach((x,w)=>Gi(x,t&&(Ke(t)?t[w]:t),n,r,s));return}if(to(r)&&!s){r.shapeFlag&512&&r.type.__asyncResolved&&r.component.subTree.component&&Gi(e,t,n,r.component.subTree);return}const o=r.shapeFlag&4?Fc(r.component):r.el,l=s?null:o,{i:a,r:u}=e,c=t&&t.r,d=a.refs===bt?a.refs={}:a.refs,f=a.setupState,p=$t(f),h=f===bt?Sw:x=>u_(d,x)?!1:Ot(p,x),b=(x,w)=>!(w&&u_(d,w));if(c!=null&&c!==u){if(c_(t),jt(c))d[c]=null,h(c)&&(f[c]=null);else if(Et(c)){const x=t;b(c,x.k)&&(c.value=null),x.k&&(d[x.k]=null)}}if(nt(u))Da(u,a,12,[l,d]);else{const x=jt(u),w=Et(u);if(x||w){const k=()=>{if(e.f){const C=x?h(u)?f[u]:d[u]:b()||!e.k?u.value:d[e.k];if(s)Ke(C)&&Ay(C,o);else if(Ke(C))C.includes(o)||C.push(o);else if(x)d[u]=[o],h(u)&&(f[u]=d[u]);else{const S=[o];b(u,e.k)&&(u.value=S),e.k&&(d[e.k]=S)}}else x?(d[u]=l,h(u)&&(f[u]=l)):w&&(b(u,e.k)&&(u.value=l),e.k&&(d[e.k]=l))};if(l){const C=()=>{k(),$f.delete(e)};C.id=-1,$f.set(e,C),bn(C,n)}else c_(e),k()}}}function c_(e){const t=$f.get(e);t&&(t.flags|=8,$f.delete(e))}let d_=!1;const xi=()=>{d_||(console.error("Hydration completed but contains mismatches."),d_=!0)},y5=e=>e.namespaceURI.includes("svg")&&e.tagName!=="foreignObject",b5=e=>e.namespaceURI.includes("MathML"),gd=e=>{if(e.nodeType===1){if(y5(e))return"svg";if(b5(e))return"mathml"}},qi=e=>e.nodeType===8;function _5(e){const{mt:t,p:n,o:{patchProp:r,createText:s,nextSibling:o,parentNode:l,remove:a,insert:u,createComment:c}}=e,d=(S,E)=>{if(!E.hasChildNodes()){n(null,S,E),kf(),E._vnode=S;return}f(E.firstChild,S,null,null,null),kf(),E._vnode=S},f=(S,E,T,O,P,I=!1)=>{I=I||!!E.dynamicChildren;const M=qi(S)&&S.data==="[",D=()=>x(S,E,T,O,P,M),{type:L,ref:F,shapeFlag:N,patchFlag:j}=E;let q=S.nodeType;E.el=S,j===-2&&(I=!1,E.dynamicChildren=null);let W=null;switch(L){case no:q!==3?E.children===""?(u(E.el=s(""),l(S),S),W=S):W=D():(S.data!==E.children&&(xi(),S.data=E.children),W=o(S));break;case dn:C(S)?(W=o(S),k(E.el=S.content.firstChild,S,T)):q!==8||M?W=D():W=o(S);break;case Yo:if(M&&(S=o(S),q=S.nodeType),q===1||q===3){W=S;const X=!E.children.length;for(let ee=0;ee{I=I||!!E.dynamicChildren;const{type:M,dynamicProps:D,props:L,patchFlag:F,shapeFlag:N,dirs:j,transition:q}=E,W=M==="input"||M==="option",X=!!D;if(W||X||F!==-1){j&&_s(E,null,T,"created");let ee=!1;if(C(S)){ee=L2(null,q)&&T&&T.vnode.props&&T.vnode.props.appear;const fe=S.content.firstChild;if(ee){const le=fe.getAttribute("class");le&&(fe.$cls=le),q.beforeEnter(fe)}k(fe,S,T),E.el=S=fe}if(N&16&&!(L&&(L.innerHTML||L.textContent))){let fe=h(S.firstChild,E,S,T,O,P,I);for(fe&&!Xd(S,1)&&xi();fe;){const le=fe;fe=fe.nextSibling,a(le)}}else if(N&8){let fe=E.children;fe[0]===` -`&&(S.tagName==="PRE"||S.tagName==="TEXTAREA")&&(fe=fe.slice(1));const{textContent:le}=S;le!==fe&&le!==fe.replace(/\r\n|\r/g,` -`)&&(Xd(S,0)||xi(),S.textContent=E.children)}if(L){if(W||X||!I||F&48){const fe=S.tagName.includes("-"),le=S.namespaceURI.includes("svg")?"svg":S.namespaceURI.includes("MathML")?"mathml":void 0;for(const re in L)if(W&&(re.endsWith("value")||re==="indeterminate")||Pc(re)&&!Ul(re)||re[0]==="."||fe&&!Ul(re)||D&&D.includes(re)){if(k5(S,re,L[re]))continue;r(S,re,null,L[re],le,T)}}else if(L.onClick)r(S,"onClick",null,L.onClick,void 0,T);else if(F&4&&Cs(L.style))for(const fe in L.style)L.style[fe]}let ce;(ce=L&&L.onVnodeBeforeMount)&&lr(ce,T,E),j&&_s(E,null,T,"beforeMount"),((ce=L&&L.onVnodeMounted)||j||ee)&&U2(()=>{ce&&lr(ce,T,E),ee&&q.enter(S),j&&_s(E,null,T,"mounted")},O)}return S.nextSibling},h=(S,E,T,O,P,I,M)=>{M=M||!!E.dynamicChildren;const D=E.children,L=D.length;let F=!1;for(let N=0;N{const{slotScopeIds:M}=E;M&&(P=P?P.concat(M):M);const D=l(S),L=h(o(S),E,D,T,O,P,I);return L&&qi(L)&&L.data==="]"?o(E.anchor=L):(xi(),u(E.anchor=c("]"),D,L),L)},x=(S,E,T,O,P,I)=>{if($5(S,E)||xi(),E.el=null,I){const L=w(S);for(;;){const F=o(S);if(F&&F!==L)a(F);else break}}const M=o(S),D=l(S);return a(S),n(null,E,D,M,T,O,gd(D),P),T&&(T.vnode.el=E.el,$m(T,E.el)),M},w=(S,E="[",T="]")=>{let O=0;for(;S;)if(S=o(S),S&&qi(S)&&(S.data===E&&O++,S.data===T)){if(O===0)return o(S);O--}return S},k=(S,E,T)=>{const O=E.parentNode;O&&O.replaceChild(S,E);let P=T;for(;P;)P.vnode.el===E&&(P.vnode.el=P.subTree.el=S),P=P.parent},C=S=>S.nodeType===1&&S.tagName==="TEMPLATE";return[d,f]}const x5=new Set(["src","srcset","href","poster"]);function k5(e,t,n){return x5.has(t)?e.getAttribute(t)===(n==null?null:`${n}`):!1}const Cf="data-allow-mismatch",w5={0:"text",1:"children",2:"class",3:"style",4:"attribute"};function Xd(e,t){if(t===0||t===1)for(;e&&!e.hasAttribute(Cf);)e=e.parentElement;return Hy(e&&e.getAttribute(Cf),t)}function Hy(e,t){if(e==null)return!1;if(e==="")return!0;{const n=e.split(",");return t===0&&n.includes("children")?!0:n.includes(w5[t])}}function $5(e,t){return Xd(e.parentElement,1)||C5(e)||S5(t)}function C5(e){return e.nodeType===1&&Hy(e.getAttribute(Cf),1)}function S5({props:e}){const t=e&&e[Cf];return typeof t=="string"&&Hy(t,1)}const E5=am().requestIdleCallback||(e=>setTimeout(e,1)),O5=am().cancelIdleCallback||(e=>clearTimeout(e)),T5=(e=1e4)=>t=>{const n=E5(t,{timeout:e});return()=>O5(n)};function A5(e){const{top:t,left:n,bottom:r,right:s}=e.getBoundingClientRect(),{innerHeight:o,innerWidth:l}=window;return(t>0&&t0&&r0&&n0&&s(t,n)=>{const r=new IntersectionObserver(s=>{for(const o of s)if(o.isIntersecting){r.disconnect(),t();break}},e);return n(s=>{if(s instanceof Element){if(A5(s))return t(),r.disconnect(),!1;r.observe(s)}}),()=>r.disconnect()},M5=e=>t=>{if(e){const n=matchMedia(e);if(n.matches)t();else return n.addEventListener("change",t,{once:!0}),()=>n.removeEventListener("change",t)}},D5=(e=[])=>(t,n)=>{jt(e)&&(e=[e]);let r=!1;const s=l=>{r||(r=!0,o(),t(),l.target.dispatchEvent(new l.constructor(l.type,l)))},o=()=>{n(l=>{for(const a of e)l.removeEventListener(a,s)})};return n(l=>{for(const a of e)l.addEventListener(a,s,{once:!0})}),o};function V5(e,t){if(qi(e)&&e.data==="["){let n=1,r=e.nextSibling;for(;r;){if(r.nodeType===1){if(t(r)===!1)break}else if(qi(r))if(r.data==="]"){if(--n===0)break}else r.data==="["&&n++;r=r.nextSibling}}else t(e)}const to=e=>!!e.type.__asyncLoader;function I5(e){nt(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:r,delay:s=200,hydrate:o,timeout:l,suspensible:a=!0,onError:u}=e;let c=null,d,f=0;const p=()=>(f++,c=null,h()),h=()=>{let b;return c||(b=c=t().catch(x=>{if(x=x instanceof Error?x:new Error(String(x)),u)return new Promise((w,k)=>{u(x,()=>w(p()),()=>k(x),f+1)});throw x}).then(x=>b!==c&&c?c:(x&&(x.__esModule||x[Symbol.toStringTag]==="Module")&&(x=x.default),d=x,x)))};return K({name:"AsyncComponentWrapper",__asyncLoader:h,__asyncHydrate(b,x,w){const k=b.isConnected;let C=!1;(x.bu||(x.bu=[])).push(()=>C=!0);const S=()=>{C||!b.parentNode||k&&!b.isConnected||w()},E=o?()=>{const T=o(S,O=>V5(b,O));T&&(x.bum||(x.bum=[])).push(T)}:S;d?E():h().then(()=>!x.isUnmounted&&E())},get __asyncResolved(){return d},setup(){const b=In;if(jy(b),d)return()=>vd(d,b);const x=T=>{c=null,fi(T,b,13,!r)};if(a&&b.suspense||Zl)return h().then(T=>()=>vd(T,b)).catch(T=>(x(T),()=>r?v(r,{error:T}):null));const w=U(!1),k=U(),C=U(!!s);let S,E;return nn(()=>{S!=null&&clearTimeout(S),E!=null&&clearTimeout(E)}),s&&(E=setTimeout(()=>{b.isUnmounted||(C.value=!1)},s)),l!=null&&(S=setTimeout(()=>{if(!b.isUnmounted&&!w.value&&!k.value){const T=new Error(`Async component timed out after ${l}ms.`);x(T),k.value=T}},l)),h().then(()=>{b.isUnmounted||(w.value=!0,b.parent&&Nc(b.parent.vnode)&&b.parent.update())}).catch(T=>{if(b.isUnmounted){c=null;return}x(T),k.value=T}),()=>{if(w.value&&d)return vd(d,b);if(k.value&&r)return v(r,{error:k.value});if(n&&!C.value)return vd(n,b)}}})}function vd(e,t){const{ref:n,props:r,children:s,ce:o}=t.vnode,l=v(e,r,s);return l.ref=n,l.ce=o,delete t.vnode.ce,l}const Nc=e=>e.type.__isKeepAlive,R5={name:"KeepAlive",__isKeepAlive:!0,props:{include:[String,RegExp,Array],exclude:[String,RegExp,Array],max:[String,Number]},setup(e,{slots:t}){const n=zt(),r=n.ctx;if(!r.renderer)return()=>{const C=t.default&&t.default();return C&&C.length===1?C[0]:C};const s=new Map,o=new Set;let l=null;const a=n.suspense,{renderer:{p:u,m:c,um:d,o:{createElement:f}}}=r,p=f("div");r.activate=(C,S,E,T,O)=>{const P=C.component;c(C,S,E,0,a),u(P.vnode,C,S,E,P,a,T,C.slotScopeIds,O),bn(()=>{P.isDeactivated=!1,P.a&&Ki(P.a);const I=C.props&&C.props.onVnodeMounted;I&&lr(I,P.parent,C)},a)},r.deactivate=C=>{const S=C.component;Ef(S.m),Ef(S.a),c(C,p,null,1,a),bn(()=>{S.da&&Ki(S.da);const E=C.props&&C.props.onVnodeUnmounted;E&&lr(E,S.parent,C),S.isDeactivated=!0},a)};function h(C){wh(C),d(C,n,a,!0)}function b(C){s.forEach((S,E)=>{const T=sv(to(S)?S.type.__asyncResolved||{}:S.type);T&&!C(T)&&x(E)})}function x(C){const S=s.get(C);S&&(!l||!Yr(S,l))?h(S):l&&wh(l),s.delete(C),o.delete(C)}ye(()=>[e.include,e.exclude],([C,S])=>{C&&b(E=>du(C,E)),S&&b(E=>!du(S,E))},{flush:"post",deep:!0});let w=null;const k=()=>{w!=null&&(Of(n.subTree.type)?bn(()=>{const C=yd(n.subTree);C.component&&s.set(w,C)},n.subTree.suspense):s.set(w,yd(n.subTree)))};return mt(k),Lc(k),Kn(()=>{s.forEach(C=>{const{subTree:S,suspense:E}=n,T=yd(S);if(C.type===T.type&&C.key===T.key){wh(T);const O=T.component.da;O&&bn(O,E);return}h(C)})}),()=>{if(w=null,!t.default)return l=null;const C=t.default(),S=C[0];if(C.length>1)return l=null,C;if(!fo(S)||!(S.shapeFlag&4)&&!(S.shapeFlag&128))return l=null,S;let E=yd(S);if(E.type===dn)return l=null,E;const T=E.type,O=sv(to(E)?E.type.__asyncResolved||{}:T),{include:P,exclude:I,max:M}=e;if(P&&(!O||!du(P,O))||I&&O&&du(I,O))return E.shapeFlag&=-257,l=E,S;const D=E.key==null?T:E.key,L=s.get(D);return E.el&&(E=ss(E),S.shapeFlag&128&&(S.ssContent=E)),w=D,L?(E.el=L.el,E.component=L.component,E.transition&&co(E,E.transition),E.shapeFlag|=512,o.delete(D),o.add(D)):(o.add(D),M&&o.size>parseInt(M,10)&&x(o.values().next().value)),E.shapeFlag|=256,l=E,Of(S.type)?S:E}}},N5=R5;function du(e,t){return Ke(e)?e.some(n=>du(n,t)):jt(e)?e.split(",").includes(t):cP(e)?(e.lastIndex=0,e.test(t)):!1}function f2(e,t){m2(e,"a",t)}function p2(e,t){m2(e,"da",t)}function m2(e,t,n=In){const r=e.__wdc||(e.__wdc=()=>{let s=n;for(;s;){if(s.isDeactivated)return;s=s.parent}return e()});if(bm(t,r,n),n){let s=n.parent;for(;s&&s.parent;)Nc(s.parent.vnode)&&L5(r,t,n,s),s=s.parent}}function L5(e,t,n,r){const s=bm(t,e,r,!0);nn(()=>{Ay(r[t],s)},n)}function wh(e){e.shapeFlag&=-257,e.shapeFlag&=-513}function yd(e){return e.shapeFlag&128?e.ssContent:e}function bm(e,t,n=In,r=!1){if(n){const s=n[e]||(n[e]=[]),o=t.__weh||(t.__weh=(...l)=>{ao();const a=Va(n),u=$r(t,n,e,l);return a(),uo(),u});return r?s.unshift(o):s.push(o),o}}const bo=e=>(t,n=In)=>{(!Zl||e==="sp")&&bm(e,(...r)=>t(...r),n)},h2=bo("bm"),mt=bo("m"),zy=bo("bu"),Lc=bo("u"),Kn=bo("bum"),nn=bo("um"),g2=bo("sp"),v2=bo("rtg"),y2=bo("rtc");function b2(e,t=In){bm("ec",e,t)}const Ky="components",F5="directives";function Wy(e,t){return Gy(Ky,e,!0,t)||e}const _2=Symbol.for("v-ndc");function Pn(e){return jt(e)?Gy(Ky,e,!1)||e:e||_2}function B5(e){return Gy(F5,e)}function Gy(e,t,n=!0,r=!1){const s=Rn||In;if(s){const o=s.type;if(e===Ky){const a=sv(o,!1);if(a&&(a===t||a===fn(t)||a===Mc(fn(t))))return o}const l=f_(s[e]||o[e],t)||f_(s.appContext[e],t);return!l&&r?o:l}}function f_(e,t){return e&&(e[t]||e[fn(t)]||e[Mc(fn(t))])}function ne(e,t,n,r){let s;const o=n&&n[r],l=Ke(e);if(l||jt(e)){const a=l&&Cs(e);let u=!1,c=!1;a&&(u=!mr(e),c=Os(e),e=fm(e)),s=new Array(e.length);for(let d=0,f=e.length;dt(a,u,void 0,o&&o[u]));else{const a=Object.keys(e);s=new Array(a.length);for(let u=0,c=a.length;u{const o=r.fn(...s);return o&&(o.key=r.key),o}:r.fn)}return e}function he(e,t,n,r,s,o){if(n==null&&(n={}),Rn.ce||Rn.parent&&to(Rn.parent)&&Rn.parent.ce){const c=o!=null&&n.key==null?Nt({},n,{key:o}):n,d=Object.keys(c).length>0;return t!=="default"&&(c.name=t),y(),B(H,null,[v("slot",c,r&&r())],d?-2:64)}let l=e[t];l&&l._c&&(l._d=!1);const a=ro.length;y();let u;try{const c=l&&Jy(l(n)),d=n.key||o||c&&c.key;u=B(H,{key:(d&&!wr(d)?d:`_${t}`)+(!c&&r?"_fb":"")},c||(r?r():[]),c&&e._===1?64:-2)}catch(c){for(let d=ro.length;d>a;d--)Cm();throw c}finally{l&&l._c&&(l._d=!0)}return!s&&u.scopeId&&(u.slotScopeIds=[u.scopeId+"-s"]),u}function Jy(e){return e.some(t=>fo(t)?!(t.type===dn||t.type===H&&!Jy(t.children)):!0)?e:null}function _m(e,t){const n={};for(const r in e)n[t&&/[A-Z]/.test(r)?`on:${r}`:zi(r)]=e[r];return n}const Yg=e=>e?K2(e)?Fc(e):Yg(e.parent):null,$u=Nt(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Yg(e.parent),$root:e=>Yg(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>Xy(e),$forceUpdate:e=>e.f||(e.f=()=>{Ny(e.update)}),$nextTick:e=>e.n||(e.n=ot.bind(e.proxy)),$watch:e=>f5.bind(e)}),$h=(e,t)=>e!==bt&&!e.__isScriptSetup&&Ot(e,t),Xg={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:n,setupState:r,data:s,props:o,accessCache:l,type:a,appContext:u}=e;if(t[0]!=="$"){const p=l[t];if(p!==void 0)switch(p){case 1:return r[t];case 2:return s[t];case 4:return n[t];case 3:return o[t]}else{if($h(r,t))return l[t]=1,r[t];if(s!==bt&&Ot(s,t))return l[t]=2,s[t];if(Ot(o,t))return l[t]=3,o[t];if(n!==bt&&Ot(n,t))return l[t]=4,n[t];Qg&&(l[t]=0)}}const c=$u[t];let d,f;if(c)return t==="$attrs"&&qn(e.attrs,"get",""),c(e);if((d=a.__cssModules)&&(d=d[t]))return d;if(n!==bt&&Ot(n,t))return l[t]=4,n[t];if(f=u.config.globalProperties,Ot(f,t))return f[t]},set({_:e},t,n){const{data:r,setupState:s,ctx:o}=e;return $h(s,t)?(s[t]=n,!0):r!==bt&&Ot(r,t)?(r[t]=n,!0):Ot(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(o[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:r,appContext:s,props:o,type:l}},a){let u;return!!(n[a]||e!==bt&&a[0]!=="$"&&Ot(e,a)||$h(t,a)||Ot(o,a)||Ot(r,a)||Ot($u,a)||Ot(s.config.globalProperties,a)||(u=l.__cssModules)&&u[a])},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:Ot(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}},q5=Nt({},Xg,{get(e,t){if(t!==Symbol.unscopables)return Xg.get(e,t,e)},has(e,t){return t[0]!=="_"&&!hP(t)}});function U5(){return null}function j5(){return null}function H5(e){}function z5(e){}function K5(){return null}function W5(){}function G5(e,t){return null}function xm(){return x2().slots}function km(){return x2().attrs}function x2(e){const t=zt();return t.setupContext||(t.setupContext=J2(t))}function Zu(e){return Ke(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}function Yy(e,t){const n=Zu(e);for(const r in t){if(r.startsWith("__skip"))continue;let s=n[r];s?Ke(s)||nt(s)?s=n[r]={type:s,default:t[r]}:s.default=t[r]:s===null&&(s=n[r]={default:t[r]}),s&&t[`__skip_${r}`]&&(s.skipFactory=!0)}return n}function J5(e,t){return!e||!t?e||t:Ke(e)&&Ke(t)?e.concat(t):Nt({},Zu(e),Zu(t))}function Y5(e,t){const n={};for(const r in e)t.includes(r)||Object.defineProperty(n,r,{enumerable:!0,get:()=>e[r]});return n}function X5(e){const t=zt(),n=Zl;let r=e();nc(),n&&Xo(!1);const s=()=>{Va(t),n&&Xo(!0)},o=()=>{zt()!==t&&t.scope.off(),nc(),n&&Xo(!1)};return Py(r)&&(r=r.catch(l=>{throw s(),Promise.resolve().then(()=>Promise.resolve().then(o)),l})),[r,()=>{s(),Promise.resolve().then(o)}]}let Qg=!0;function Q5(e){const t=Xy(e),n=e.proxy,r=e.ctx;Qg=!1,t.beforeCreate&&p_(t.beforeCreate,e,"bc");const{data:s,computed:o,methods:l,watch:a,provide:u,inject:c,created:d,beforeMount:f,mounted:p,beforeUpdate:h,updated:b,activated:x,deactivated:w,beforeDestroy:k,beforeUnmount:C,destroyed:S,unmounted:E,render:T,renderTracked:O,renderTriggered:P,errorCaptured:I,serverPrefetch:M,expose:D,inheritAttrs:L,components:F,directives:N,filters:j}=t;if(c&&Z5(c,r,null),l)for(const X in l){const ee=l[X];nt(ee)&&(r[X]=ee.bind(n))}if(s){const X=s.call(n,n);Pt(X)&&(e.data=rt(X))}if(Qg=!0,o)for(const X in o){const ee=o[X],ce=nt(ee)?ee.bind(n,n):nt(ee.get)?ee.get.bind(n,n):qr,fe=!nt(ee)&&nt(ee.set)?ee.set.bind(n):qr,le=V({get:ce,set:fe});Object.defineProperty(r,X,{enumerable:!0,configurable:!0,get:()=>le.value,set:re=>le.value=re})}if(a)for(const X in a)k2(a[X],r,n,X);if(u){const X=nt(u)?u.call(n):u;Reflect.ownKeys(X).forEach(ee=>{Ic(ee,X[ee])})}d&&p_(d,e,"c");function W(X,ee){Ke(ee)?ee.forEach(ce=>X(ce.bind(n))):ee&&X(ee.bind(n))}if(W(h2,f),W(mt,p),W(zy,h),W(Lc,b),W(f2,x),W(p2,w),W(b2,I),W(y2,O),W(v2,P),W(Kn,C),W(nn,E),W(g2,M),Ke(D))if(D.length){const X=e.exposed||(e.exposed={});D.forEach(ee=>{Object.defineProperty(X,ee,{get:()=>n[ee],set:ce=>n[ee]=ce,enumerable:!0})})}else e.exposed||(e.exposed={});T&&e.render===qr&&(e.render=T),L!=null&&(e.inheritAttrs=L),F&&(e.components=F),N&&(e.directives=N),M&&jy(e)}function Z5(e,t,n=qr){Ke(e)&&(e=Zg(e));for(const r in e){const s=e[r];let o;Pt(s)?"default"in s?o=eo(s.from||r,s.default,!0):o=eo(s.from||r):o=eo(s),Et(o)?Object.defineProperty(t,r,{enumerable:!0,configurable:!0,get:()=>o.value,set:l=>o.value=l}):t[r]=o}}function p_(e,t,n){$r(Ke(e)?e.map(r=>r.bind(t.proxy)):e.bind(t.proxy),t,n)}function k2(e,t,n,r){let s=r.includes(".")?l2(n,r):()=>n[r];if(jt(e)){const o=t[e];nt(o)&&ye(s,o)}else if(nt(e))ye(s,e.bind(n));else if(Pt(e))if(Ke(e))e.forEach(o=>k2(o,t,n,r));else{const o=nt(e.handler)?e.handler.bind(n):t[e.handler];nt(o)&&ye(s,o,e)}}function Xy(e){const t=e.type,{mixins:n,extends:r}=t,{mixins:s,optionsCache:o,config:{optionMergeStrategies:l}}=e.appContext,a=o.get(t);let u;return a?u=a:!s.length&&!n&&!r?u=t:(u={},s.length&&s.forEach(c=>Sf(u,c,l,!0)),Sf(u,t,l)),Pt(t)&&o.set(t,u),u}function Sf(e,t,n,r=!1){const{mixins:s,extends:o}=t;o&&Sf(e,o,n,!0),s&&s.forEach(l=>Sf(e,l,n,!0));for(const l in t)if(!(r&&l==="expose")){const a=e8[l]||n&&n[l];e[l]=a?a(e[l],t[l]):t[l]}return e}const e8={data:m_,props:h_,emits:h_,methods:fu,computed:fu,beforeCreate:Gn,created:Gn,beforeMount:Gn,mounted:Gn,beforeUpdate:Gn,updated:Gn,beforeDestroy:Gn,beforeUnmount:Gn,destroyed:Gn,unmounted:Gn,activated:Gn,deactivated:Gn,errorCaptured:Gn,serverPrefetch:Gn,components:fu,directives:fu,watch:n8,provide:m_,inject:t8};function m_(e,t){return t?e?function(){return Nt(nt(e)?e.call(this,this):e,nt(t)?t.call(this,this):t)}:t:e}function t8(e,t){return fu(Zg(e),Zg(t))}function Zg(e){if(Ke(e)){const t={};for(let n=0;n{let d,f=bt,p;return Fy(()=>{const h=e[s];On(d,h)&&(d=h,c())}),{get(){return u(),n.get?n.get(d):d},set(h){const b=n.set?n.set(h):h;if(!On(b,d)&&!(f!==bt&&On(h,f)))return;const x=r.vnode.props,w=!!(x&&(t in x||s in x||o in x)&&(`onUpdate:${t}`in x||`onUpdate:${s}`in x||`onUpdate:${o}`in x));w||(d=h,c()),r.emit(`update:${t}`,b),On(h,f)&&(On(h,b)&&!On(b,p)||w&&f!==bt&&!On(b,d))&&c(),f=h,p=b}}});return a[Symbol.iterator]=()=>{let u=0;return{next(){return u<2?{value:u++?l||bt:a,done:!1}:{done:!0}}}},a}const $2=(e,t)=>t==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${fn(t)}Modifiers`]||e[`${dr(t)}Modifiers`];function l8(e,t,...n){if(e.isUnmounted)return;const r=e.vnode.props||bt;let s=n;const o=t.startsWith("update:"),l=o&&$2(r,t.slice(7));l&&(l.trim&&(s=n.map(d=>jt(d)?d.trim():d)),l.number&&(s=s.map(im)));let a,u=r[a=zi(t)]||r[a=zi(fn(t))];!u&&o&&(u=r[a=zi(dr(t))]),u&&$r(u,e,6,s);const c=r[a+"Once"];if(c){if(!e.emitted)e.emitted={};else if(e.emitted[a])return;e.emitted[a]=!0,$r(c,e,6,s)}}const i8=new WeakMap;function C2(e,t,n=!1){const r=n?i8:t.emitsCache,s=r.get(e);if(s!==void 0)return s;const o=e.emits;let l={},a=!1;if(!nt(e)){const u=c=>{const d=C2(c,t,!0);d&&(a=!0,Nt(l,d))};!n&&t.mixins.length&&t.mixins.forEach(u),e.extends&&u(e.extends),e.mixins&&e.mixins.forEach(u)}return!o&&!a?(Pt(e)&&r.set(e,null),null):(Ke(o)?o.forEach(u=>l[u]=null):Nt(l,o),Pt(e)&&r.set(e,l),l)}function wm(e,t){return!e||!Pc(t)?!1:(t=t.slice(2),t=t==="Once"?t:t.replace(/Once$/,""),Ot(e,t[0].toLowerCase()+t.slice(1))||Ot(e,dr(t))||Ot(e,t))}function Qd(e){const{type:t,vnode:n,proxy:r,withProxy:s,propsOptions:[o],slots:l,attrs:a,emit:u,render:c,renderCache:d,props:f,data:p,setupState:h,ctx:b,inheritAttrs:x}=e,w=Qu(e);let k,C;try{if(n.shapeFlag&4){const E=s||r,T=E;k=ir(c.call(T,E,d,f,h,p,b)),C=a}else{const E=t;k=ir(E.length>1?E(f,{attrs:a,slots:l,emit:u}):E(f,null)),C=t.props?a:u8(a)}}catch(E){ro.length=0,fi(E,e,1),k=v(dn)}let S=k;if(C&&x!==!1){const E=Object.keys(C),{shapeFlag:T}=S;E.length&&T&7&&(o&&E.some(rm)&&(C=c8(C,o)),S=ss(S,C,!1,!0))}if(n.dirs&&(S=ss(S,null,!1,!0),S.dirs=S.dirs?S.dirs.concat(n.dirs):n.dirs),n.transition){const E=vm(S.type)&&wf(S)||S;co(E,n.transition)}return k=S,Qu(w),k}function a8(e,t=!0){let n;for(let r=0;r{let t;for(const n in e)(n==="class"||n==="style"||Pc(n))&&((t||(t={}))[n]=e[n]);return t},c8=(e,t)=>{const n={};for(const r in e)(!rm(r)||!(r.slice(9)in t))&&(n[r]=e[r]);return n};function d8(e,t,n){const{props:r,children:s,component:o}=e,{props:l,children:a,patchFlag:u}=t,c=o.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&u>=0){if(u&1024)return!0;if(u&16)return r?g_(r,l,c):!!l;if(u&8){const d=t.dynamicProps;for(let f=0;fObject.create(E2),T2=e=>Object.getPrototypeOf(e)===E2;function f8(e,t,n,r=!1){const s={},o=O2();e.propsDefaults=Object.create(null),A2(e,t,s,o);for(const l in e.propsOptions[0])l in s||(s[l]=void 0);n?e.props=r?s:Ww(s):e.type.props?e.props=s:e.props=o,e.attrs=o}function p8(e,t,n,r){const{props:s,attrs:o,vnode:{patchFlag:l}}=e,a=$t(s),[u]=e.propsOptions;let c=!1;if((r||l>0)&&!(l&16)){if(l&8){const d=e.vnode.dynamicProps;for(let f=0;f{u=!0;const[p,h]=P2(f,t,!0);Nt(l,p),h&&a.push(...h)};!n&&t.mixins.length&&t.mixins.forEach(d),e.extends&&d(e.extends),e.mixins&&e.mixins.forEach(d)}if(!o&&!u)return Pt(e)&&r.set(e,Hi),Hi;if(Ke(o))for(let d=0;de==="_"||e==="_ctx"||e==="$stable",Zy=e=>Ke(e)?e.map(ir):[ir(e)],h8=(e,t,n)=>{if(t._n)return t;const r=_((...s)=>Zy(t(...s)),n);return r._c=!1,r},M2=(e,t,n)=>{const r=e._ctx;for(const s in e){if(Qy(s))continue;const o=e[s];if(nt(o))t[s]=h8(s,o,r);else if(o!=null){const l=Zy(o);t[s]=()=>l}}},D2=(e,t)=>{const n=Zy(t);e.slots.default=()=>n},V2=(e,t,n)=>{for(const r in t)(n||!Qy(r))&&(e[r]=t[r])},g8=(e,t,n)=>{const r=e.slots=O2();if(e.vnode.shapeFlag&32){const s=t._;s?(V2(r,t,n),n&&Ow(r,"_",s,!0)):M2(t,r)}else t&&D2(e,t)},v8=(e,t,n)=>{const{vnode:r,slots:s}=e;let o=!0,l=bt;if(r.shapeFlag&32){const a=t._;a?n&&a===1?o=!1:V2(s,t,n):(o=!t.$stable,M2(t,s)),l=t}else t&&(D2(e,t),l={default:1});if(o)for(const a in s)!Qy(a)&&l[a]==null&&delete s[a]},bn=U2;function I2(e){return N2(e)}function R2(e){return N2(e,_5)}function N2(e,t){const n=am();n.__VUE__=!0;const{insert:r,remove:s,patchProp:o,createElement:l,createText:a,createComment:u,setText:c,setElementText:d,parentNode:f,nextSibling:p,setScopeId:h=qr,insertStaticContent:b}=e,x=(G,se,_e,we=null,Oe=null,z=null,J=void 0,ae=null,ve=!!se.dynamicChildren)=>{if(G===se)return;G&&!Yr(G,se)&&(we=Le(G),re(G,Oe,z,!0),G=null),se.patchFlag===-2&&(ve=!1,se.dynamicChildren=null);const{type:$e,ref:Pe,shapeFlag:oe}=se;switch($e){case no:w(G,se,_e,we);break;case dn:k(G,se,_e,we);break;case Yo:G==null&&C(se,_e,we,J);break;case H:F(G,se,_e,we,Oe,z,J,ae,ve);break;default:oe&1?T(G,se,_e,we,Oe,z,J,ae,ve):oe&6?N(G,se,_e,we,Oe,z,J,ae,ve):(oe&64||oe&128)&&$e.process(G,se,_e,we,Oe,z,J,ae,ve,ue)}Pe!=null&&Oe?Gi(Pe,G&&G.ref,z,se||G,!se):Pe==null&&G&&G.ref!=null&&Gi(G.ref,null,z,G,!0)},w=(G,se,_e,we)=>{if(G==null)r(se.el=a(se.children),_e,we);else{const Oe=se.el=G.el;se.children!==G.children&&c(Oe,se.children)}},k=(G,se,_e,we)=>{G==null?r(se.el=u(se.children||""),_e,we):se.el=G.el},C=(G,se,_e,we)=>{[G.el,G.anchor]=b(G.children,se,_e,we,G.el,G.anchor)},S=({el:G,anchor:se},_e,we)=>{let Oe;for(;G&&G!==se;)Oe=p(G),r(G,_e,we),G=Oe;r(se,_e,we)},E=({el:G,anchor:se})=>{let _e;for(;G&&G!==se;)_e=p(G),s(G),G=_e;s(se)},T=(G,se,_e,we,Oe,z,J,ae,ve)=>{if(se.type==="svg"?J="svg":se.type==="math"&&(J="mathml"),G==null)O(se,_e,we,Oe,z,J,ae,ve);else{const $e=G.el&&G.el._isVueCE?G.el:null;try{$e&&$e._beginPatch(),M(G,se,Oe,z,J,ae,ve)}finally{$e&&$e._endPatch()}}},O=(G,se,_e,we,Oe,z,J,ae)=>{let ve,$e;const{props:Pe,shapeFlag:oe,transition:be,dirs:Fe}=G;if(ve=G.el=l(G.type,z,Pe&&Pe.is,Pe),oe&8?d(ve,G.children):oe&16&&I(G.children,ve,null,we,Oe,Ch(G,z),J,ae),Fe&&_s(G,null,we,"created"),P(ve,G,G.scopeId,J,we),Pe){for(const ht in Pe)ht!=="value"&&!Ul(ht)&&o(ve,ht,null,Pe[ht],z,we);"value"in Pe&&o(ve,"value",null,Pe.value,z),($e=Pe.onVnodeBeforeMount)&&lr($e,we,G)}Fe&&_s(G,null,we,"beforeMount");const Xe=L2(Oe,be);Xe&&be.beforeEnter(ve),r(ve,se,_e),(($e=Pe&&Pe.onVnodeMounted)||Xe||Fe)&&bn(()=>{try{$e&&lr($e,we,G),Xe&&be.enter(ve),Fe&&_s(G,null,we,"mounted")}finally{}},Oe)},P=(G,se,_e,we,Oe)=>{if(_e&&h(G,_e),we)for(let z=0;z{for(let $e=ve;$e{const ae=se.el=G.el;let{patchFlag:ve,dynamicChildren:$e,dirs:Pe}=se;ve|=G.patchFlag&16;const oe=G.props||bt,be=se.props||bt;let Fe;if(_e&&$l(_e,!1),(Fe=be.onVnodeBeforeUpdate)&&lr(Fe,_e,se,G),Pe&&_s(se,G,_e,"beforeUpdate"),_e&&$l(_e,!0),$e&&(!G.dynamicChildren||G.dynamicChildren.length!==$e.length)&&(ve=0,J=!1,$e=null),(oe.innerHTML&&be.innerHTML==null||oe.textContent&&be.textContent==null)&&d(ae,""),$e?D(G.dynamicChildren,$e,ae,_e,we,Ch(se,Oe),z):J||ee(G,se,ae,null,_e,we,Ch(se,Oe),z,!1),ve>0){if(ve&16)L(ae,oe,be,_e,Oe);else if(ve&2&&oe.class!==be.class&&o(ae,"class",null,be.class,Oe),ve&4&&o(ae,"style",oe.style,be.style,Oe),ve&8){const Xe=se.dynamicProps;for(let ht=0;ht{Fe&&lr(Fe,_e,se,G),Pe&&_s(se,G,_e,"updated")},we)},D=(G,se,_e,we,Oe,z,J)=>{for(let ae=0;ae{if(se!==_e){if(se!==bt)for(const z in se)!Ul(z)&&!(z in _e)&&o(G,z,se[z],null,Oe,we);for(const z in _e){if(Ul(z))continue;const J=_e[z],ae=se[z];J!==ae&&z!=="value"&&o(G,z,ae,J,Oe,we)}"value"in _e&&o(G,"value",se.value,_e.value,Oe)}},F=(G,se,_e,we,Oe,z,J,ae,ve)=>{const $e=se.el=G?G.el:a(""),Pe=se.anchor=G?G.anchor:a("");let{patchFlag:oe,dynamicChildren:be,slotScopeIds:Fe}=se;Fe&&(ae=ae?ae.concat(Fe):Fe),G==null?(r($e,_e,we),r(Pe,_e,we),I(se.children||[],_e,Pe,Oe,z,J,ae,ve)):oe>0&&oe&64&&be&&G.dynamicChildren&&G.dynamicChildren.length===be.length?(D(G.dynamicChildren,be,_e,Oe,z,J,ae),(se.key!=null||Oe&&se===Oe.subTree)&&e1(G,se,!0)):ee(G,se,_e,Pe,Oe,z,J,ae,ve)},N=(G,se,_e,we,Oe,z,J,ae,ve)=>{se.slotScopeIds=ae,G==null?se.shapeFlag&512?Oe.ctx.activate(se,_e,we,J,ve):j(se,_e,we,Oe,z,J,ve):q(G,se,ve)},j=(G,se,_e,we,Oe,z,J)=>{const ae=G.component=z2(G,we,Oe);if(Nc(G)&&(ae.ctx.renderer=ue),W2(ae,!1,J),ae.asyncDep){if(Oe&&Oe.registerDep(ae,W,J),!G.el){const ve=ae.subTree=v(dn);k(null,ve,se,_e),G.placeholder=ve.el}}else W(ae,G,se,_e,Oe,z,J)},q=(G,se,_e)=>{const we=se.component=G.component;if(d8(G,se,_e))if(we.asyncDep&&!we.asyncResolved){X(we,se,_e);return}else we.next=se,we.update();else se.el=G.el,we.vnode=se},W=(G,se,_e,we,Oe,z,J)=>{const ae=()=>{if(G.isMounted){let{next:oe,bu:be,u:Fe,parent:Xe,vnode:ht}=G;{const Ae=F2(G);if(Ae){oe&&(oe.el=ht.el,X(G,oe,J)),Ae.asyncDep.then(()=>{bn(()=>{G.isUnmounted||$e()},Oe)});return}}let it=oe,_t;$l(G,!1),oe?(oe.el=ht.el,X(G,oe,J)):oe=ht,be&&Ki(be),(_t=oe.props&&oe.props.onVnodeBeforeUpdate)&&lr(_t,Xe,oe,ht),$l(G,!0);const Zt=Qd(G),Ce=G.subTree;G.subTree=Zt,x(Ce,Zt,f(Ce.el),Le(Ce),G,Oe,z),oe.el=Zt.el,it===null&&$m(G,Zt.el),Fe&&bn(Fe,Oe),(_t=oe.props&&oe.props.onVnodeUpdated)&&bn(()=>lr(_t,Xe,oe,ht),Oe)}else{let oe;const{el:be,props:Fe}=se,{bm:Xe,m:ht,parent:it,root:_t,type:Zt}=G,Ce=to(se);if($l(G,!1),Xe&&Ki(Xe),!Ce&&(oe=Fe&&Fe.onVnodeBeforeMount)&&lr(oe,it,se),$l(G,!0),be&&ge){const Ae=()=>{G.subTree=Qd(G),ge(be,G.subTree,G,Oe,null)};Ce&&Zt.__asyncHydrate?Zt.__asyncHydrate(be,G,Ae):Ae()}else{_t.ce&&_t.ce._hasShadowRoot()&&_t.ce._injectChildStyle(Zt,G.parent?G.parent.type:void 0);const Ae=G.subTree=Qd(G);x(null,Ae,_e,we,G,Oe,z),se.el=Ae.el}if(ht&&bn(ht,Oe),!Ce&&(oe=Fe&&Fe.onVnodeMounted)){const Ae=se;bn(()=>lr(oe,it,Ae),Oe)}(se.shapeFlag&256||it&&to(it.vnode)&&it.vnode.shapeFlag&256)&&G.a&&bn(G.a,Oe),G.isMounted=!0,se=_e=we=null}};G.scope.on();const ve=G.effect=new Wu(ae);G.scope.off();const $e=G.update=ve.run.bind(ve),Pe=G.job=ve.runIfDirty.bind(ve);Pe.i=G,Pe.id=G.uid,ve.scheduler=()=>Ny(Pe),$l(G,!0),$e()},X=(G,se,_e)=>{se.component=G;const we=G.vnode.props;G.vnode=se,G.next=null,p8(G,se.props,we,_e),v8(G,se.children,_e),ao(),l_(G),uo()},ee=(G,se,_e,we,Oe,z,J,ae,ve=!1)=>{const $e=G&&G.children,Pe=G?G.shapeFlag:0,oe=se.children,{patchFlag:be,shapeFlag:Fe}=se;if(be>0){if(be&128){fe($e,oe,_e,we,Oe,z,J,ae,ve);return}else if(be&256){ce($e,oe,_e,we,Oe,z,J,ae,ve);return}}Fe&8?(Pe&16&&Se($e,Oe,z),oe!==$e&&d(_e,oe)):Pe&16?Fe&16?fe($e,oe,_e,we,Oe,z,J,ae,ve):Se($e,Oe,z,!0):(Pe&8&&d(_e,""),Fe&16&&I(oe,_e,we,Oe,z,J,ae,ve))},ce=(G,se,_e,we,Oe,z,J,ae,ve)=>{G=G||Hi,se=se||Hi;const $e=G.length,Pe=se.length,oe=Math.min($e,Pe);let be;for(be=0;bePe?Se(G,Oe,z,!0,!1,oe):I(se,_e,we,Oe,z,J,ae,ve,oe)},fe=(G,se,_e,we,Oe,z,J,ae,ve)=>{let $e=0;const Pe=se.length;let oe=G.length-1,be=Pe-1;for(;$e<=oe&&$e<=be;){const Fe=G[$e],Xe=se[$e]=ve?js(se[$e]):ir(se[$e]);if(Yr(Fe,Xe))x(Fe,Xe,_e,null,Oe,z,J,ae,ve);else break;$e++}for(;$e<=oe&&$e<=be;){const Fe=G[oe],Xe=se[be]=ve?js(se[be]):ir(se[be]);if(Yr(Fe,Xe))x(Fe,Xe,_e,null,Oe,z,J,ae,ve);else break;oe--,be--}if($e>oe){if($e<=be){const Fe=be+1,Xe=Febe)for(;$e<=oe;)re(G[$e],Oe,z,!0),$e++;else{const Fe=$e,Xe=$e,ht=new Map;for($e=Xe;$e<=be;$e++){const yr=se[$e]=ve?js(se[$e]):ir(se[$e]);yr.key!=null&&ht.set(yr.key,$e)}let it,_t=0;const Zt=be-Xe+1;let Ce=!1,Ae=0;const Ie=new Array(Zt);for($e=0;$e=Zt){re(yr,Oe,z,!0);continue}let us;if(yr.key!=null)us=ht.get(yr.key);else for(it=Xe;it<=be;it++)if(Ie[it-Xe]===0&&Yr(yr,se[it])){us=it;break}us===void 0?re(yr,Oe,z,!0):(Ie[us-Xe]=$e+1,us>=Ae?Ae=us:Ce=!0,x(yr,se[us],_e,null,Oe,z,J,ae,ve),_t++)}const Co=Ce?y8(Ie):Hi;for(it=Co.length-1,$e=Zt-1;$e>=0;$e--){const yr=Xe+$e,us=se[yr],Qb=se[yr+1],Zb=yr+1{const{el:z,type:J,transition:ae,children:ve,shapeFlag:$e}=G;if($e&6){le(G.component.subTree,se,_e,we);return}if($e&128){G.suspense.move(se,_e,we);return}if($e&64){J.move(G,se,_e,ue);return}if(J===H){r(z,se,_e);for(let oe=0;oeae.enter(z),Oe));else{const{leave:oe,delayLeave:be,afterLeave:Fe}=ae,Xe=()=>{G.ctx.isUnmounted?s(z):r(z,se,_e)},ht=()=>{const it=z._isLeaving||!!z[Dr];z._isLeaving&&z[Dr](!0),ae.persisted&&!it?Xe():oe(z,()=>{Xe(),Fe&&Fe()})};be?be(z,Xe,ht):ht()}else r(z,se,_e)},re=(G,se,_e,we=!1,Oe=!1)=>{const{type:z,props:J,ref:ae,children:ve,dynamicChildren:$e,shapeFlag:Pe,patchFlag:oe,dirs:be,cacheIndex:Fe,memo:Xe}=G;if(oe===-2&&(Oe=!1),ae!=null&&(ao(),Gi(ae,null,_e,G,!0),uo()),Fe!=null&&(se.renderCache[Fe]=void 0),Pe&256){se.ctx.deactivate(G);return}const ht=Pe&1&&be,it=!to(G);let _t;if(it&&(_t=J&&J.onVnodeBeforeUnmount)&&lr(_t,se,G),Pe&6)De(G.component,_e,we);else{if(Pe&128){G.suspense.unmount(_e,we);return}ht&&_s(G,null,se,"beforeUnmount"),Pe&64?G.type.remove(G,se,_e,ue,we):$e&&!$e.hasOnce&&(z!==H||oe>0&&oe&64)?Se($e,se,_e,!1,!0):(z===H&&oe&384||!Oe&&Pe&16)&&Se(ve,se,_e),we&&Q(G)}const Zt=Xe!=null&&Fe==null;(it&&(_t=J&&J.onVnodeUnmounted)||ht||Zt)&&bn(()=>{_t&&lr(_t,se,G),ht&&_s(G,null,se,"unmounted"),Zt&&(G.el=null)},_e)},Q=G=>{const{type:se,el:_e,anchor:we,transition:Oe}=G;if(se===H){Ee(_e,we);return}if(se===Yo){E(G);return}const z=()=>{s(_e),Oe&&!Oe.persisted&&Oe.afterLeave&&Oe.afterLeave()};if(G.shapeFlag&1&&Oe&&!Oe.persisted){const{leave:J,delayLeave:ae}=Oe,ve=()=>J(_e,z);ae?ae(G.el,z,ve):ve()}else z()},Ee=(G,se)=>{let _e;for(;G!==se;)_e=p(G),s(G),G=_e;s(se)},De=(G,se,_e)=>{const{bum:we,scope:Oe,job:z,subTree:J,um:ae,m:ve,a:$e}=G;Ef(ve),Ef($e),we&&Ki(we),Oe.stop(),z&&(z.flags|=8,re(J,G,se,_e)),ae&&bn(ae,se),bn(()=>{G.isUnmounted=!0},se)},Se=(G,se,_e,we=!1,Oe=!1,z=0)=>{for(let J=z;J{if(G.shapeFlag&6)return Le(G.component.subTree);if(G.shapeFlag&128)return G.suspense.next();const se=p(G.anchor||G.el),_e=se&&se[i2];return _e?p(_e):se};let Be=!1;const me=(G,se,_e)=>{let we;G==null?se._vnode&&(re(se._vnode,null,null,!0),we=se._vnode.component):x(se._vnode||null,G,se,null,null,null,_e),se._vnode=G,Be||(Be=!0,l_(we),kf(),Be=!1)},ue={p:x,um:re,m:le,r:Q,mt:j,mc:I,pc:ee,pbc:D,n:Le,o:e};let te,ge;return t&&([te,ge]=t(ue)),{render:me,hydrate:te,createApp:s8(me,te)}}function Ch({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function $l({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function L2(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function e1(e,t,n=!1){const r=e.children,s=t.children;if(Ke(r)&&Ke(s))for(let o=0;o>1,e[n[a]]0&&(t[r]=n[o-1]),n[o]=r)}}for(o=n.length,l=n[o-1];o-- >0;)n[o]=l,l=t[l];return n}function F2(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:F2(t)}function Ef(e){if(e)for(let t=0;te.__isSuspense;let tv=0;const b8={name:"Suspense",__isSuspense:!0,process(e,t,n,r,s,o,l,a,u,c){if(e==null)x8(t,n,r,s,o,l,a,u,c);else{if(o&&o.deps>0&&!e.suspense.isInFallback){t.suspense=e.suspense,t.suspense.vnode=t,t.el=e.el;return}k8(e,t,n,r,s,l,a,u,c)}},hydrate:w8,normalize:$8},_8=b8;function ec(e,t){const n=e.props&&e.props[t];nt(n)&&n()}function x8(e,t,n,r,s,o,l,a,u){const{p:c,o:{createElement:d}}=u,f=d("div"),p=e.suspense=q2(e,s,r,t,f,n,o,l,a,u);c(null,p.pendingBranch=e.ssContent,f,null,r,p,o,l),p.deps>0?(ec(e,"onPending"),ec(e,"onFallback"),c(null,e.ssFallback,t,n,r,null,o,l),Ji(p,e.ssFallback)):p.resolve(!1,!0)}function k8(e,t,n,r,s,o,l,a,{p:u,um:c,o:{createElement:d}}){const f=t.suspense=e.suspense;f.vnode=t,t.el=e.el;const p=t.ssContent,h=t.ssFallback,{activeBranch:b,pendingBranch:x,isInFallback:w,isHydrating:k}=f;if(x)f.pendingBranch=p,Yr(x,p)?(u(x,p,f.hiddenContainer,null,s,f,o,l,a),f.deps<=0?f.resolve():w&&!k&&!f.isFallbackMountPending&&(u(b,h,n,r,s,null,o,l,a),Ji(f,h))):(f.pendingId=tv++,k?(f.isHydrating=!1,f.activeBranch=x):c(x,s,f),f.deps=0,f.effects.length=0,f.hiddenContainer=d("div"),w?(u(null,p,f.hiddenContainer,null,s,f,o,l,a),f.deps<=0?f.resolve():f.isFallbackMountPending||(u(b,h,n,r,s,null,o,l,a),Ji(f,h))):b&&Yr(b,p)?(u(b,p,n,r,s,f,o,l,a),f.resolve(!0)):(u(null,p,f.hiddenContainer,null,s,f,o,l,a),f.deps<=0&&f.resolve()));else if(b&&Yr(b,p))u(b,p,n,r,s,f,o,l,a),Ji(f,p);else if(ec(t,"onPending"),f.pendingBranch=p,p.shapeFlag&512?f.pendingId=p.component.suspenseId:f.pendingId=tv++,u(null,p,f.hiddenContainer,null,s,f,o,l,a),f.deps<=0)f.resolve();else{const{timeout:C,pendingId:S}=f;C>0?setTimeout(()=>{f.pendingId===S&&f.fallback(h)},C):C===0&&f.fallback(h)}}function q2(e,t,n,r,s,o,l,a,u,c,d=!1){const{p:f,m:p,um:h,n:b,o:{parentNode:x,remove:w}}=c;let k;const C=C8(e);C&&t&&t.pendingBranch&&(k=t.pendingId,t.deps++);const S=e.props?vf(e.props.timeout):void 0,E=o,T={vnode:e,parent:t,parentComponent:n,namespace:l,container:r,hiddenContainer:s,deps:0,pendingId:tv++,timeout:typeof S=="number"?S:-1,activeBranch:null,isFallbackMountPending:!1,pendingBranch:null,isInFallback:!d,isHydrating:d,isUnmounted:!1,effects:[],resolve(O=!1,P=!1){const{vnode:I,activeBranch:M,pendingBranch:D,pendingId:L,effects:F,parentComponent:N,container:j,isInFallback:q}=T;let W=!1;if(T.isHydrating)T.isHydrating=!1;else if(!O){W=M&&D.transition&&D.transition.mode==="out-in";let ce=!1;W&&(M.transition.afterLeave=()=>{L===T.pendingId&&(p(D,j,o===E&&!ce?b(M):o,0),Yu(F),q&&I.ssFallback&&(I.ssFallback.el=null))}),M&&!T.isFallbackMountPending&&(x(M.el)===j&&(o=b(M),ce=!0),h(M,N,T,!0),!W&&q&&I.ssFallback&&bn(()=>I.ssFallback.el=null,T)),W||p(D,j,o,0)}T.isFallbackMountPending=!1,Ji(T,D),T.pendingBranch=null,T.isInFallback=!1;let X=T.parent,ee=!1;for(;X;){if(X.pendingBranch){for(let ce=0;ce{if(T.isFallbackMountPending=!1,!T.isInFallback)return;const q=T.vnode.ssFallback;f(null,q,D,F,M,null,L,a,u),Ji(T,q)},j=O.transition&&O.transition.mode==="out-in";j&&(T.isFallbackMountPending=!0,I.transition.afterLeave=N),T.isInFallback=!0,h(I,M,null,!0),j||N()},move(O,P,I){T.activeBranch&&p(T.activeBranch,O,P,I),T.container=O},next(){return T.activeBranch&&b(T.activeBranch)},registerDep(O,P,I){const M=!!T.pendingBranch;M&&T.deps++;const D=O.vnode.el;O.asyncDep.catch(L=>{fi(L,O,0)}).then(L=>{if(O.isUnmounted||T.isUnmounted||T.pendingId!==O.suspenseId)return;nc(),O.asyncResolved=!0;const{vnode:F}=O;nv(O,L,!1),D&&(F.el=D);const N=!D&&O.subTree.el;P(O,F,x(D||O.subTree.el),D?null:b(O.subTree),T,l,I),N&&(F.placeholder=null,w(N)),$m(O,F.el),M&&--T.deps===0&&T.resolve()})},unmount(O,P){T.isUnmounted=!0,T.activeBranch&&h(T.activeBranch,n,O,P),T.pendingBranch&&h(T.pendingBranch,n,O,P)}};return T}function w8(e,t,n,r,s,o,l,a,u){const c=t.suspense=q2(t,r,n,e.parentNode,document.createElement("div"),null,s,o,l,a,!0),d=u(e,c.pendingBranch=t.ssContent,n,c,o,l);return c.deps===0&&c.resolve(!1,!0),d}function $8(e){const{shapeFlag:t,children:n}=e,r=t&32;e.ssContent=y_(r?n.default:n),e.ssFallback=r?y_(n.fallback):v(dn)}function y_(e){let t;if(nt(e)){const n=Ql&&e._c;n&&(e._d=!1,y()),e=e(),n&&(e._d=!0,t=Un,Cm())}return Ke(e)&&(e=a8(e)),e=ir(e),t&&!e.dynamicChildren&&(e.dynamicChildren=t.filter(n=>n!==e)),e}function U2(e,t){t&&t.pendingBranch?Ke(e)?t.effects.push(...e):t.effects.push(e):Yu(e)}function Ji(e,t){e.activeBranch=t;const{vnode:n,parentComponent:r}=e;let s=t.el;for(;!s&&t.component;)t=t.component.subTree,s=t.el;n.el=s,r&&r.subTree===n&&(r.vnode.el=s,$m(r,s))}function C8(e){const t=e.props&&e.props.suspensible;return t!=null&&t!==!1}const H=Symbol.for("v-fgt"),no=Symbol.for("v-txt"),dn=Symbol.for("v-cmt"),Yo=Symbol.for("v-stc"),ro=[];let Un=null;function y(e=!1){ro.push(Un=e?null:[])}function Cm(){ro.pop(),Un=ro[ro.length-1]||null}let Ql=1;function tc(e,t=!1){Ql+=e,e<0&&Un&&t&&(Un.hasOnce=!0)}function j2(e){return e.dynamicChildren=Ql>0?Un||Hi:null,Cm(),Ql>0&&Un&&Un.push(e),e}function $(e,t,n,r,s,o){return j2(g(e,t,n,r,s,o,!0))}function B(e,t,n,r,s){return j2(v(e,t,n,r,s,!0))}function fo(e){return e?e.__v_isVNode===!0:!1}function Yr(e,t){return e.type===t.type&&e.key===t.key}function S8(e){}const H2=({key:e})=>e??null,Zd=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?jt(e)||Et(e)||nt(e)?{i:Rn,r:e,k:t,f:!!n}:e:null);function g(e,t=null,n=null,r=0,s=null,o=e===H?0:1,l=!1,a=!1){const u={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&H2(t),ref:t&&Zd(t),scopeId:gm,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:o,patchFlag:r,dynamicProps:s,dynamicChildren:null,appContext:null,ctx:Rn};return a?(Tf(u,n),o&128&&e.normalize(u)):n&&(u.shapeFlag|=jt(n)?8:16),Ql>0&&!l&&Un&&(u.patchFlag>0||o&6)&&u.patchFlag!==32&&Un.push(u),u}const v=E8;function E8(e,t=null,n=null,r=0,s=null,o=!1){if((!e||e===_2)&&(e=dn),fo(e)){const a=ss(e,t,!0);return n&&Tf(a,n),Ql>0&&!o&&Un&&(a.shapeFlag&6?Un[Un.indexOf(e)]=a:Un.push(a)),a.patchFlag=-2,a}if(I8(e)&&(e=e.__vccOpts),t){t=ct(t);let{class:a,style:u}=t;a&&!jt(a)&&(t.class=pe(a)),Pt(u)&&(Vc(u)&&!Ke(u)&&(u=Nt({},u)),t.style=kt(u))}const l=jt(e)?1:Of(e)?128:vm(e)?64:Pt(e)?4:nt(e)?2:0;return g(e,t,n,r,s,l,o,!0)}function ct(e){return e?Vc(e)||T2(e)?Nt({},e):e:null}function ss(e,t,n=!1,r=!1){const{props:s,ref:o,patchFlag:l,children:a,transition:u}=e,c=t?je(s||{},t):s,d={__v_isVNode:!0,__v_skip:!0,type:e.type,props:c,key:c&&H2(c),ref:t&&t.ref?n&&o?Ke(o)?o.concat(Zd(t)):[o,Zd(t)]:Zd(t):o,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:a,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==H?l===-1?16:l|16:l,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:u,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&ss(e.ssContent),ssFallback:e.ssFallback&&ss(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return u&&r&&co(d,u.clone(d)),d}function A(e=" ",t=0){return v(no,null,e,t)}function O8(e,t){const n=v(Yo,null,e);return n.staticCount=t,n}function R(e="",t=!1){return t?(y(),B(dn,null,e)):v(dn,null,e)}function ir(e){return e==null||typeof e=="boolean"?v(dn):Ke(e)?v(H,null,e.slice()):fo(e)?js(e):v(no,null,String(e))}function js(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:ss(e)}function Tf(e,t){let n=0;const{shapeFlag:r}=e;if(t==null)t=null;else if(Ke(t))n=16;else if(typeof t=="object")if(r&65){const s=t.default;s&&(s._c&&(s._d=!1),Tf(e,s()),s._c&&(s._d=!0));return}else{n=32;const s=t._;!s&&!T2(t)?t._ctx=Rn:s===3&&Rn&&(Rn.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else if(nt(t)){if(r&65){Tf(e,{default:t});return}t={default:t,_ctx:Rn},n=32}else t=String(t),r&64?(n=16,t=[A(t)]):n=8;e.children=t,e.shapeFlag|=n}function je(...e){const t={};for(let n=0;nIn||Rn;let Af,Xo;{const e=am(),t=(n,r)=>{let s;return(s=e[n])||(s=e[n]=[]),s.push(r),o=>{s.length>1?s.forEach(l=>l(o)):s[0](o)}};Af=t("__VUE_INSTANCE_SETTERS__",n=>In=n),Xo=t("__VUE_SSR_SETTERS__",n=>Zl=n)}const Va=e=>{const t=In;return Af(e),e.scope.on(),()=>{e.scope.off(),Af(t)}},nc=()=>{In&&In.scope.off(),Af(null)};function K2(e){return e.vnode.shapeFlag&4}let Zl=!1;function W2(e,t=!1,n=!1){t&&Xo(t);const{props:r,children:s}=e.vnode,o=K2(e);f8(e,r,o,t),g8(e,s,n||t);const l=o?P8(e,t):void 0;return t&&Xo(!1),l}function P8(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,Xg);const{setup:r}=n;if(r){ao();const s=e.setupContext=r.length>1?J2(e):null,o=Va(e),l=Da(r,e,0,[e.props,s]),a=Py(l);if(uo(),o(),(a||e.sp)&&!to(e)&&jy(e),a){if(l.then(nc,nc),t)return l.then(u=>{Xo(!0);try{nv(e,u,t)}finally{Xo(!1)}}).catch(u=>{fi(u,e,0)});e.asyncDep=l}else nv(e,l,t)}else G2(e,t)}function nv(e,t,n){nt(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:Pt(t)&&(e.setupState=Ry(t)),G2(e,n)}let Pf,rv;function M8(e){Pf=e,rv=t=>{t.render._rc&&(t.withProxy=new Proxy(t.ctx,q5))}}const D8=()=>!Pf;function G2(e,t,n){const r=e.type;if(!e.render){if(!t&&Pf&&!r.render){const s=r.template||Xy(e).template;if(s){const{isCustomElement:o,compilerOptions:l}=e.appContext.config,{delimiters:a,compilerOptions:u}=r,c=Nt(Nt({isCustomElement:o,delimiters:a},l),u);r.render=Pf(s,c)}}e.render=r.render||qr,rv&&rv(e)}{const s=Va(e);ao();try{Q5(e)}finally{uo(),s()}}}const V8={get(e,t){return qn(e,"get",""),e[t]}};function J2(e){const t=n=>{e.exposed=n||{}};return{attrs:new Proxy(e.attrs,V8),slots:e.slots,emit:e.emit,expose:t}}function Fc(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(Ry(sa(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in $u)return $u[n](e)},has(t,n){return n in t||n in $u}})):e.proxy}function sv(e,t=!0){return nt(e)?e.displayName||e.name:e.name||t&&e.__name}function I8(e){return nt(e)&&"__vccOpts"in e}const V=(e,t)=>YP(e,t,Zl);function Rt(e,t,n){try{tc(-1);const r=arguments.length;return r===2?Pt(t)&&!Ke(t)?fo(t)?v(e,null,[t]):v(e,t):v(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):r===3&&fo(n)&&(n=[n]),v(e,t,n))}finally{tc(1)}}function R8(){}function Sm(e,t,n,r){const s=n[r];if(s&&Y2(s,e))return s;const o=t();return o.memo=e.slice(),o.cacheIndex=r,n[r]=o}function Y2(e,t){const n=e.memo;if(n.length!=t.length)return!1;for(let r=0;r0&&Un&&Un.push(e),!0}const X2="3.5.42",N8=qr,L8=o5,F8=Pi,B8=r2,q8={createComponentInstance:z2,setupComponent:W2,renderComponentRoot:Qd,setCurrentRenderingInstance:Qu,isVNode:fo,normalizeVNode:ir,getComponentPublicInstance:Fc,ensureValidVNode:Jy,pushWarningContext:t5,popWarningContext:n5},U8=q8,j8=null,H8=null,z8=null;/** -* @vue/runtime-dom v3.5.42 -* (c) 2018-present Yuxi (Evan) You and Vue contributors -* @license MIT -**/let ov;const b_=typeof window<"u"&&window.trustedTypes;if(b_)try{ov=b_.createPolicy("vue",{createHTML:e=>e})}catch{}const Q2=ov?e=>ov.createHTML(e):e=>e,K8="http://www.w3.org/2000/svg",W8="http://www.w3.org/1998/Math/MathML",qs=typeof document<"u"?document:null,__=qs&&qs.createElement("template"),Z2={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const s=t==="svg"?qs.createElementNS(K8,e):t==="mathml"?qs.createElementNS(W8,e):n?qs.createElement(e,{is:n}):qs.createElement(e);return e==="select"&&r&&r.multiple!=null&&s.setAttribute("multiple",r.multiple),s},createText:e=>qs.createTextNode(e),createComment:e=>qs.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>qs.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,s,o){const l=n?n.previousSibling:t.lastChild;if(s&&(s===o||s.nextSibling))for(;t.insertBefore(s.cloneNode(!0),n),!(s===o||!(s=s.nextSibling)););else{__.innerHTML=Q2(r==="svg"?`${e}`:r==="mathml"?`${e}`:e);const a=__.content;if(r==="svg"||r==="mathml"){const u=a.firstChild;for(;u.firstChild;)a.appendChild(u.firstChild);a.removeChild(u)}t.insertBefore(a,n)}return[l?l.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},So="transition",Ga="animation",ia=Symbol("_vtc"),e$={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},t$=Nt({},Uy,e$),G8=e=>(e.displayName="Transition",e.props=t$,e),J8=G8((e,{slots:t})=>Rt(c2,n$(e),t)),Cl=(e,t=[])=>{Ke(e)?e.forEach(n=>n(...t)):e&&e(...t)},x_=e=>e?Ke(e)?e.some(t=>t.length>1):e.length>1:!1;function n$(e){const t={};for(const F in e)F in e$||(t[F]=e[F]);if(e.css===!1)return t;const{name:n="v",type:r,duration:s,enterFromClass:o=`${n}-enter-from`,enterActiveClass:l=`${n}-enter-active`,enterToClass:a=`${n}-enter-to`,appearFromClass:u=o,appearActiveClass:c=l,appearToClass:d=a,leaveFromClass:f=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:h=`${n}-leave-to`}=e,b=Y8(s),x=b&&b[0],w=b&&b[1],{onBeforeEnter:k,onEnter:C,onEnterCancelled:S,onLeave:E,onLeaveCancelled:T,onBeforeAppear:O=k,onAppear:P=C,onAppearCancelled:I=S}=t,M=(F,N,j,q)=>{F._enterCancelled=q,Mo(F,N?d:a),Mo(F,N?c:l),j&&j()},D=(F,N)=>{F._isLeaving=!1,Mo(F,f),Mo(F,h),Mo(F,p),N&&N()},L=F=>(N,j)=>{const q=F?P:C,W=()=>M(N,F,j);Cl(q,[N,W]),k_(()=>{Mo(N,F?u:o),ps(N,F?d:a),x_(q)||w_(N,r,x,W)})};return Nt(t,{onBeforeEnter(F){Cl(k,[F]),ps(F,o),ps(F,l)},onBeforeAppear(F){Cl(O,[F]),ps(F,u),ps(F,c)},onEnter:L(!1),onAppear:L(!0),onLeave(F,N){F._isLeaving=!0;const j=()=>D(F,N);ps(F,f),F._enterCancelled?(ps(F,p),lv(F)):(lv(F),ps(F,p)),k_(()=>{F._isLeaving&&(Mo(F,f),ps(F,h),x_(E)||w_(F,r,w,j))}),Cl(E,[F,j])},onEnterCancelled(F){M(F,!1,void 0,!0),Cl(S,[F])},onAppearCancelled(F){M(F,!0,void 0,!0),Cl(I,[F])},onLeaveCancelled(F){D(F),Cl(T,[F])}})}function Y8(e){if(e==null)return null;if(Pt(e))return[Sh(e.enter),Sh(e.leave)];{const t=Sh(e);return[t,t]}}function Sh(e){return vf(e)}function ps(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[ia]||(e[ia]=new Set)).add(t)}function Mo(e,t){t.split(/\s+/).forEach(r=>r&&e.classList.remove(r));const n=e[ia];n&&(n.delete(t),n.size||(e[ia]=void 0))}function k_(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let X8=0;function w_(e,t,n,r){const s=e._endId=++X8,o=()=>{s===e._endId&&r()};if(n!=null)return setTimeout(o,n);const{type:l,timeout:a,propCount:u}=r$(e,t);if(!l)return r();const c=l+"end";let d=0;const f=()=>{e.removeEventListener(c,p),o()},p=h=>{h.target===e&&++d>=u&&f()};setTimeout(()=>{d(n[b]||"").split(", "),s=r(`${So}Delay`),o=r(`${So}Duration`),l=$_(s,o),a=r(`${Ga}Delay`),u=r(`${Ga}Duration`),c=$_(a,u);let d=null,f=0,p=0;t===So?l>0&&(d=So,f=l,p=o.length):t===Ga?c>0&&(d=Ga,f=c,p=u.length):(f=Math.max(l,c),d=f>0?l>c?So:Ga:null,p=d?d===So?o.length:u.length:0);const h=d===So&&/\b(?:transform|all)(?:,|$)/.test(r(`${So}Property`).toString());return{type:d,timeout:f,propCount:p,hasTransform:h}}function $_(e,t){for(;e.lengthC_(n)+C_(e[r])))}function C_(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function lv(e){return(e?e.ownerDocument:document).body.offsetHeight}function Q8(e,t,n){const r=e[ia];r&&(t=(t?[t,...r]:[...r]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const Mf=Symbol("_vod"),t1=Symbol("_vsh"),sl={name:"show",beforeMount(e,{value:t},{transition:n}){e[Mf]=e.style.display==="none"?"":e.style.display,n&&t?n.beforeEnter(e):Ja(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:r}){!t!=!n&&(r?t?(r.beforeEnter(e),Ja(e,!0),r.enter(e)):r.leave(e,()=>{Ja(e,!1)}):Ja(e,t))},beforeUnmount(e,{value:t}){Ja(e,t)}};function Ja(e,t){e.style.display=t?e[Mf]:"none",e[t1]=!t}function Z8(){sl.getSSRProps=({value:e})=>{if(!e)return{style:{display:"none"}}}}const s$=Symbol("");function e3(e){const t=zt();if(!t)return;const n=t.ut=(s=e(t.proxy))=>{Array.from(document.querySelectorAll(`[data-v-owner="${t.uid}"]`)).forEach(o=>Df(o,s))},r=()=>{const s=e(t.proxy);t.ce?Df(t.ce,s):iv(t.subTree,s),n(s)};zy(()=>{Yu(r)}),mt(()=>{ye(r,qr,{flush:"post"});const s=new MutationObserver(r);s.observe(t.subTree.el.parentNode,{childList:!0}),nn(()=>s.disconnect())})}function iv(e,t){if(e.shapeFlag&128){const n=e.suspense;e=n.activeBranch,n.pendingBranch&&!n.isHydrating&&n.effects.push(()=>{iv(n.activeBranch,t)})}for(;e.component;)e=e.component.subTree;if(e.shapeFlag&1&&e.el)Df(e.el,t);else if(e.type===H)e.children.forEach(n=>iv(n,t));else if(e.type===Yo){let{el:n,anchor:r}=e;for(;n&&(Df(n,t),n!==r);)n=n.nextSibling}}function Df(e,t){if(e.nodeType===1){const n=e.style;let r="";for(const s in t){const o=wP(t[s]);n.setProperty(`--${s}`,o),r+=`--${s}: ${o};`}n[s$]=r}}const t3=/(?:^|;)\s*display\s*:/;function n3(e,t,n){const r=e.style,s=jt(n);let o=!1;if(n&&!s){if(t)if(jt(t))for(const l of t.split(";")){const a=l.slice(0,l.indexOf(":")).trim();n[a]==null&&pu(r,a,"")}else for(const l in t)n[l]==null&&pu(r,l,"");for(const l in n){l==="display"&&(o=!0);const a=n[l];a!=null?s3(e,l,!jt(t)&&t?t[l]:void 0,a)||pu(r,l,a):pu(r,l,"")}}else if(s){if(t!==n){const l=r[s$];l&&(n+=";"+l),r.cssText=n,o=t3.test(n)}}else t&&e.removeAttribute("style");Mf in e&&(e[Mf]=o?r.display:"",e[t1]&&(r.display="none"))}const bd=/\s*!important$/;function pu(e,t,n){if(Ke(n))n.forEach(r=>pu(e,t,r));else if(n==null&&(n=""),t.startsWith("--"))bd.test(n)?e.setProperty(t,n.replace(bd,""),"important"):e.setProperty(t,n);else{const r=r3(e,t);bd.test(n)?e.setProperty(dr(r),n.replace(bd,""),"important"):e[r]=n}}const S_=["Webkit","Moz","ms"],Eh={};function r3(e,t){const n=Eh[t];if(n)return n;let r=fn(t);if(r!=="filter"&&r in e)return Eh[t]=r;r=Mc(r);for(let s=0;sOh||(c3.then(()=>Oh=0),Oh=Date.now());function f3(e,t){const n=r=>{if(!r._vts)r._vts=Date.now();else if(r._vts<=n.attached)return;const s=n.value;if(Ke(s)){const o=r.stopImmediatePropagation;r.stopImmediatePropagation=()=>{o.call(r),r._stopped=!0};const l=s.slice(),a=[r];for(let u=0;ue.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,o$=(e,t,n,r,s,o)=>{const l=s==="svg";t==="class"?Q8(e,r,l):t==="style"?n3(e,n,r):Pc(t)?rm(t)||l3(e,t,n,r,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):p3(e,t,r,l))?(T_(e,t,r),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&O_(e,t,r,l,o,t!=="value")):e._isVueCE&&(m3(e,t)||e._def.__asyncLoader&&(/[A-Z]/.test(t)||!jt(r)))?T_(e,fn(t),r,o,t):(t==="true-value"?e._trueValue=r:t==="false-value"&&(e._falseValue=r),O_(e,t,r,l))};function p3(e,t,n,r){if(r)return!!(t==="innerHTML"||t==="textContent"||t in e&&P_(t)&&nt(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="autocorrect"||t==="sandbox"&&e.tagName==="IFRAME"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const s=e.tagName;if(s==="IMG"||s==="VIDEO"||s==="CANVAS"||s==="SOURCE")return!1}return P_(t)&&jt(n)?!1:t in e}function m3(e,t){const n=e._def.props;if(!n)return!1;const r=fn(t);return Array.isArray(n)?n.some(s=>fn(s)===r):Object.keys(n).some(s=>fn(s)===r)}const M_={};function l$(e,t,n){let r=K(e,t);sm(r)&&(r=Nt({},r,t));class s extends Em{constructor(l){super(r,l,n)}}return s.def=r,s}const h3=((e,t)=>l$(e,t,If)),g3=typeof HTMLElement<"u"?HTMLElement:class{};class Em extends g3{constructor(t,n={},r=sc){super(),this._def=t,this._props=n,this._createApp=r,this._isVueCE=!0,this._instance=null,this._app=null,this._nonce=this._def.nonce,this._connected=!1,this._resolved=!1,this._patching=!1,this._dirty=!1,this._numberProps=null,this._styleChildren=new WeakSet,this._styleAnchors=new WeakMap,this._ob=null,this.shadowRoot&&r!==sc?this._root=this.shadowRoot:t.shadowRoot!==!1?(this.attachShadow(Nt({},t.shadowRootOptions,{mode:"open"})),this._root=this.shadowRoot):this._root=this}connectedCallback(){if(!this.isConnected)return;!this.shadowRoot&&!this._resolved&&this._parseSlots(),this._connected=!0;let t=this;for(;t=t&&(t.assignedSlot||t.parentNode||t.host);)if(t instanceof Em){this._parent=t;break}this._instance||(this._resolved?this._mount(this._def):t&&t._pendingResolve?this._pendingResolve=t._pendingResolve.then(()=>{if(this._pendingResolve=void 0,this.isConnected)return this._resolveDef()}):this._resolveDef())}_setParent(t=this._parent){t&&(this._instance.parent=t._instance,this._inheritParentContext(t))}_inheritParentContext(t=this._parent){t&&this._app&&Object.setPrototypeOf(this._app._context.provides,t._instance.provides)}disconnectedCallback(){this._connected=!1,ot(()=>{this._connected||(this._ob&&(this._ob.disconnect(),this._ob=null),this._app&&this._app.unmount(),this._instance&&(this._instance.ce=void 0),this._app=this._instance=null,this._teleportTargets&&(this._teleportTargets.clear(),this._teleportTargets=void 0))})}_processMutations(t){for(const n of t)this._setAttr(n.attributeName)}_resolveDef(){if(this._pendingResolve)return this._pendingResolve;for(let r=0;r{this._resolved=!0,this._pendingResolve=void 0;const{props:o,styles:l}=r;let a;if(o&&!Ke(o))for(const u in o){const c=o[u];(c===Number||c&&c.type===Number)&&(u in this._props&&(this._props[u]=vf(this._props[u])),(a||(a=Object.create(null)))[fn(u)]=!0)}this._numberProps=a,this._resolveProps(r),this.shadowRoot&&this._applyStyles(l),this._mount(r)},n=this._def.__asyncLoader;if(n)return this._pendingResolve=n().then(r=>{r.configureApp=this._def.configureApp,t(this._def=r,!0)}),this._pendingResolve;t(this._def)}_mount(t){this._app=this._createApp(t),this._inheritParentContext(),t.configureApp&&t.configureApp(this._app),this._app._ceVNode=this._createVNode(),this._app.mount(this._root);const n=this._instance&&this._instance.exposed;if(n)for(const r in n)Ot(this,r)||Object.defineProperty(this,r,{get:()=>i(n[r])})}_resolveProps(t){const{props:n}=t,r=Ke(n)?n:Object.keys(n||{});for(const s of Object.keys(this))s[0]!=="_"&&r.includes(s)&&this._setProp(s,this[s]);for(const s of r.map(fn))Object.defineProperty(this,s,{get(){return this._getProp(s)},set(o){this._setProp(s,o,!0,!this._patching)}})}_setAttr(t){if(t.startsWith("data-v-"))return;const n=this.hasAttribute(t);let r=n?this.getAttribute(t):M_;const s=fn(t);n&&this._numberProps&&this._numberProps[s]&&(r=vf(r)),this._setProp(s,r,!1,!0)}_getProp(t){return this._props[t]}_setProp(t,n,r=!0,s=!1){if(n!==this._props[t]&&(this._dirty=!0,n===M_?delete this._props[t]:(this._props[t]=n,t==="key"&&this._app&&(this._app._ceVNode.key=n)),s&&this._instance&&this._update(),r)){const o=this._ob;o&&(this._processMutations(o.takeRecords()),o.disconnect()),n===!0?this.setAttribute(dr(t),""):typeof n=="string"||typeof n=="number"?this.setAttribute(dr(t),n+""):n||this.removeAttribute(dr(t)),o&&o.observe(this,{attributes:!0})}}_update(){const t=this._createVNode();this._app&&(t.appContext=this._app._context),y$(t,this._root)}_createVNode(){const t={};this.shadowRoot||(t.onVnodeMounted=t.onVnodeUpdated=this._renderSlots.bind(this));const n=v(this._def,Nt(t,this._props));return this._instance||(n.ce=r=>{this._instance=r,r.ce=this,r.isCE=!0;const s=(o,l)=>{this.dispatchEvent(new CustomEvent(o,sm(l[0])?Nt({detail:l},l[0]):{detail:l}))};r.emit=(o,...l)=>{s(o,l),dr(o)!==o&&s(dr(o),l)},this._setParent()}),n}_applyStyles(t,n,r){if(!t)return;if(n){if(n===this._def||this._styleChildren.has(n))return;this._styleChildren.add(n)}const s=this._nonce,o=this.shadowRoot,l=r?this._getStyleAnchor(r)||this._getStyleAnchor(this._def):this._getRootStyleInsertionAnchor(o);let a=null;for(let u=t.length-1;u>=0;u--){const c=document.createElement("style");s&&c.setAttribute("nonce",s),c.textContent=t[u],o.insertBefore(c,a||l),a=c,u===0&&(r||this._styleAnchors.set(this._def,c),n&&this._styleAnchors.set(n,c))}}_getStyleAnchor(t){if(!t)return null;const n=this._styleAnchors.get(t);return n&&n.parentNode===this.shadowRoot?n:(n&&this._styleAnchors.delete(t),null)}_getRootStyleInsertionAnchor(t){for(let n=0;n(delete e.props.mode,e),_3=b3({name:"TransitionGroup",props:Nt({},t$,{tag:String,moveClass:String}),setup(e,{slots:t}){const n=zt(),r=qy();let s,o;return Lc(()=>{if(!s.length)return;const l=e.moveClass||`${e.name||"v"}-move`;if(!$3(s[0].el,n.vnode.el,l)){s=[];return}s.forEach(x3),s.forEach(k3);const a=s.filter(w3);lv(n.vnode.el),a.forEach(u=>{const c=u.el,d=c.style;ps(c,l),d.transform=d.webkitTransform=d.transitionDuration="";const f=c[Vf]=p=>{p&&p.target!==c||(!p||p.propertyName.endsWith("transform"))&&(c.removeEventListener("transitionend",f),c[Vf]=null,Mo(c,l))};c.addEventListener("transitionend",f)}),s=[]}),()=>{const l=$t(e),a=n$(l);let u=l.tag||H;if(s=[],o)for(let c=0;c{a.split(/\s+/).forEach(u=>u&&r.classList.remove(u))}),n.split(/\s+/).forEach(a=>a&&r.classList.add(a)),r.style.display="none";const o=t.nodeType===1?t:t.parentNode;o.appendChild(r);const{hasTransform:l}=r$(r);return o.removeChild(r),l}const ol=e=>{const t=e.props["onUpdate:modelValue"]||!1;return Ke(t)?n=>Ki(t,n):t};function C3(e){e.target.composing=!0}function V_(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const _r=Symbol("_assign"),_d=Symbol("_initialValue");function Th(e,t,n){return t&&(e=e.trim()),n&&(e=im(e)),e}const po={created(e,{modifiers:{lazy:t,trim:n,number:r}},s){e.parentNode&&(e.type==="text"?e[_d]=e.defaultValue.replace(/[\r\n]/g,""):e.type==="textarea"&&(e[_d]=e.defaultValue.replace(/\r\n?/g,` -`))),e[_r]=ol(s);const o=r||s.props&&s.props.type==="number";Ks(e,t?"change":"input",l=>{l.target.composing||e[_r](Th(e.value,n,o))}),(n||o)&&Ks(e,"change",()=>{e.value=Th(e.value,n,o)}),t||(Ks(e,"compositionstart",C3),Ks(e,"compositionend",V_),Ks(e,"change",V_))},mounted(e,{value:t,modifiers:{trim:n,number:r}}){const s=t??"",o=e[_d];delete e[_d],o!==void 0&&(e.type==="text"||e.type==="textarea")&&e.value!==o?e[_r](Th(e.value,n,r)):e.value=s},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:r,trim:s,number:o}},l){if(e[_r]=ol(l),e.composing)return;const a=(o||e.type==="number")&&!/^0\d/.test(e.value)?im(e.value):e.value,u=t??"";if(a===u)return;const c=e.getRootNode();(c instanceof Document||c instanceof ShadowRoot)&&c.activeElement===e&&e.type!=="range"&&(r&&t===n||s&&e.value.trim()===u)||(e.value=u)}},n1={deep:!0,created(e,t,n){e[_r]=ol(n),Ks(e,"change",()=>{const r=e._modelValue,s=aa(e),o=e.checked,l=e[_r];if(Ke(r)){const a=um(r,s),u=a!==-1;if(o&&!u)l(r.concat(s));else if(!o&&u){const c=[...r];c.splice(a,1),l(c)}}else if(Es(r)){const a=new Set(r);o?a.add(s):a.delete(s),l(a)}else l(f$(e,o))})},mounted:I_,beforeUpdate(e,t,n){e[_r]=ol(n),I_(e,t,n)}};function I_(e,{value:t,oldValue:n},r){e._modelValue=t;let s;if(Ke(t))s=um(t,r.props.value)>-1;else if(Es(t))s=t.has(r.props.value);else{if(t===n)return;s=Kr(t,f$(e,!0))}e.checked!==s&&(e.checked=s)}const Om={created(e,{value:t},n){e.checked=Kr(t,n.props.value),e[_r]=ol(n),Ks(e,"change",()=>{e[_r](aa(e))})},beforeUpdate(e,{value:t,oldValue:n},r){e[_r]=ol(r),t!==n&&(e.checked=Kr(t,r.props.value))}},rc={deep:!0,created(e,{value:t,modifiers:{number:n}},r){e._modelValue=t,Ks(e,"change",()=>{const s=Array.prototype.filter.call(e.options,u=>u.selected).map(u=>n?im(aa(u)):aa(u)),o=e.multiple,l=o?Es(e._modelValue)?new Set(s):s:s[0],a=e._pendingValue=[o,o?Ke(l)?s.slice():s:l];try{e[_r](l)}finally{ot(()=>{e._pendingValue===a&&(e._pendingValue=void 0)})}}),e[_r]=ol(r)},mounted(e,{value:t}){R_(e,t)},beforeUpdate(e,{value:t},n){e._modelValue=t,e[_r]=ol(n)},updated(e,{value:t}){const n=e._pendingValue;e._pendingValue=void 0,(!n||n[0]!==e.multiple||!S3(t,n[1],n[0]))&&R_(e,t)}};function S3(e,t,n){if(!n||Ke(e))return Kr(e,t);if(Es(e)){if(e.size!==t.length)return!1;for(const r of t)if(!e.has(r))return!1;return!0}return!1}function R_(e,t){const n=e.multiple,r=Ke(t);if(!(n&&!r&&!Es(t))){for(let s=0,o=e.options.length;sString(c)===String(a)):l.selected=um(t,a)>-1}else l.selected=t.has(a);else if(Kr(aa(l),t)){e.selectedIndex!==s&&(e.selectedIndex=s);return}}!n&&e.selectedIndex!==-1&&(e.selectedIndex=-1)}}function aa(e){return"_value"in e?e._value:e.value}function f$(e,t){const n=t?"_trueValue":"_falseValue";return n in e?e[n]:t}const p$={created(e,t,n){xd(e,t,n,null,"created")},mounted(e,t,n){xd(e,t,n,null,"mounted")},beforeUpdate(e,t,n,r){xd(e,t,n,r,"beforeUpdate")},updated(e,t,n,r){xd(e,t,n,r,"updated")}};function m$(e,t){switch(e){case"SELECT":return rc;case"TEXTAREA":return po;default:switch(t){case"checkbox":return n1;case"radio":return Om;default:return po}}}function xd(e,t,n,r,s){const l=m$(e.tagName,n.props&&n.props.type)[s];l&&l(e,t,n,r)}function E3(){po.getSSRProps=({value:e})=>({value:e}),Om.getSSRProps=({value:e},t)=>{if(t.props&&Kr(t.props.value,e))return{checked:!0}},n1.getSSRProps=({value:e},t)=>{if(Ke(e)){if(t.props&&um(e,t.props.value)>-1)return{checked:!0}}else if(Es(e)){if(t.props&&e.has(t.props.value))return{checked:!0}}else if(e)return{checked:!0}},p$.getSSRProps=(e,t)=>{if(typeof t.type!="string")return;const n=m$(t.type.toUpperCase(),t.props&&t.props.type);if(n.getSSRProps)return n.getSSRProps(e,t)}}const O3=["ctrl","shift","alt","meta"],T3={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>O3.some(n=>e[`${n}Key`]&&!t.includes(n))},Ne=(e,t)=>{if(!e)return e;const n=e._withMods||(e._withMods={}),r=t.join(".");return n[r]||(n[r]=((s,...o)=>{for(let l=0;l{const n=e._withKeys||(e._withKeys={}),r=t.join(".");return n[r]||(n[r]=(s=>{if(!("key"in s))return;const o=dr(s.key);if(t.some(l=>l===o||A3[l]===o))return e(s)}))},h$=Nt({patchProp:o$},Z2);let Cu,N_=!1;function g$(){return Cu||(Cu=I2(h$))}function v$(){return Cu=N_?Cu:R2(h$),N_=!0,Cu}const y$=((...e)=>{g$().render(...e)}),P3=((...e)=>{v$().hydrate(...e)}),sc=((...e)=>{const t=g$().createApp(...e),{mount:n}=t;return t.mount=r=>{const s=_$(r);if(!s)return;const o=t._component;!nt(o)&&!o.render&&!o.template&&(o.template=s.innerHTML),s.nodeType===1&&(s.textContent="");const l=n(s,!1,b$(s));return s instanceof Element&&(s.removeAttribute("v-cloak"),s.setAttribute("data-v-app","")),l},t}),If=((...e)=>{const t=v$().createApp(...e),{mount:n}=t;return t.mount=r=>{const s=_$(r);if(s)return n(s,!0,b$(s))},t});function b$(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function _$(e){return jt(e)?document.querySelector(e):e}let L_=!1;const M3=()=>{L_||(L_=!0,E3(),Z8())};/** -* vue v3.5.42 -* (c) 2018-present Yuxi (Evan) You and Vue contributors -* @license MIT -**/const D3=()=>{},V3=Object.freeze(Object.defineProperty({__proto__:null,BaseTransition:c2,BaseTransitionPropsValidators:Uy,Comment:dn,DeprecationTypes:z8,EffectScope:My,ErrorCodes:s5,ErrorTypeStrings:L8,Fragment:H,KeepAlive:N5,ReactiveEffect:Wu,Static:Yo,Suspense:_8,Teleport:By,Text:no,TrackOpTypes:XP,Transition:J8,TransitionGroup:c$,TriggerOpTypes:QP,VueElement:Em,assertNumber:r5,callWithAsyncErrorHandling:$r,callWithErrorHandling:Da,camelize:fn,capitalize:Mc,cloneVNode:ss,compatUtils:H8,compile:D3,computed:V,createApp:sc,createBlock:B,createCommentVNode:R,createElementBlock:$,createElementVNode:g,createHydrationRenderer:R2,createPropsRestProxy:Y5,createRenderer:I2,createSSRApp:If,createSlots:pl,createStaticVNode:O8,createTextVNode:A,createVNode:v,customRef:hm,defineAsyncComponent:I5,defineComponent:K,defineCustomElement:l$,defineEmits:j5,defineExpose:H5,defineModel:W5,defineOptions:z5,defineProps:U5,defineSSRCustomElement:h3,defineSlots:K5,devtools:F8,effect:CP,effectScope:cm,getCurrentInstance:zt,getCurrentScope:Ma,getCurrentWatcher:ZP,getTransitionRawChildren:ym,guardReactiveProps:ct,h:Rt,handleError:fi,hasInjectionContext:d5,hydrate:P3,hydrateOnIdle:T5,hydrateOnInteraction:D5,hydrateOnMediaQuery:M5,hydrateOnVisible:P5,initCustomFormatter:R8,initDirectivesForSSR:M3,inject:eo,isMemoSame:Y2,isProxy:Vc,isReactive:Cs,isReadonly:Os,isRef:Et,isRuntimeOnly:D8,isShallow:mr,isVNode:fo,markRaw:sa,mergeDefaults:Yy,mergeModels:J5,mergeProps:je,nextTick:ot,nodeOps:Z2,normalizeClass:pe,normalizeProps:lt,normalizeStyle:kt,onActivated:f2,onBeforeMount:h2,onBeforeUnmount:Kn,onBeforeUpdate:zy,onDeactivated:p2,onErrorCaptured:b2,onMounted:mt,onRenderTracked:y2,onRenderTriggered:v2,onScopeDispose:Dc,onServerPrefetch:g2,onUnmounted:nn,onUpdated:Lc,onWatcherCleanup:Qw,openBlock:y,patchProp:o$,popScopeId:u5,provide:Ic,proxyRefs:Ry,pushScopeId:a5,queuePostFlushCb:Yu,reactive:rt,readonly:bf,ref:U,registerRuntimeCompiler:M8,render:y$,renderList:ne,renderSlot:he,resolveComponent:Wy,resolveDirective:B5,resolveDynamicComponent:Pn,resolveFilter:j8,resolveTransitionHooks:la,setBlockTracking:tc,setDevtoolsHook:B8,setTransitionHooks:co,shallowReactive:Ww,shallowReadonly:Ro,shallowRef:yo,ssrContextKey:s2,ssrUtils:U8,stop:SP,toDisplayString:m,toHandlerKey:zi,toHandlers:_m,toRaw:$t,toRef:Yw,toRefs:ln,toValue:Ln,transformVNodeArgs:S8,triggerRef:Jw,unref:i,useAttrs:km,useCssModule:y3,useCssVars:e3,useHost:i$,useId:Yd,useModel:o8,useSSRContext:o2,useShadowRoot:v3,useSlots:xm,useTemplateRef:v5,useTransitionState:qy,vModelCheckbox:n1,vModelDynamic:p$,vModelRadio:Om,vModelSelect:rc,vModelText:po,vShow:sl,version:X2,warn:N8,watch:ye,watchEffect:Cr,watchPostEffect:Ly,watchSyncEffect:Fy,withAsyncContext:X5,withCtx:_,withDefaults:G5,withDirectives:jn,withKeys:Wt,withMemo:Sm,withModifiers:Ne,withScopeId:c5},Symbol.toStringTag,{value:"Module"})),F_=typeof globalThis=="object"&&globalThis||typeof window=="object"&&window||typeof self=="object"&&self||typeof global=="object"&&global||(function(){return this})();function I3(e,t,{signal:n,edges:r}={}){let s,o=null;const l=r!=null&&r.includes("leading"),a=r==null||r.includes("trailing"),u=()=>{o!==null&&(e.apply(s,o),s=void 0,o=null)},c=()=>{a&&u(),h()};let d=null;const f=()=>{d!=null&&clearTimeout(d),d=setTimeout(()=>{d=null,c()},t)},p=()=>{d!==null&&(clearTimeout(d),d=null)},h=()=>{p(),s=void 0,o=null},b=()=>{u()},x=function(...w){if(n!=null&&n.aborted)return;s=this,o=w;const k=d==null;f(),l&&k&&u()};return x.schedule=f,x.cancel=h,x.flush=b,n==null||n.addEventListener("abort",h,{once:!0}),x}function x$(){}function r1(e){return e==null||typeof e!="object"&&typeof e!="function"}function s1(e){return ArrayBuffer.isView(e)&&!(e instanceof DataView)}function R3(e){if(r1(e))return e;if(Array.isArray(e)||s1(e)||e instanceof ArrayBuffer||typeof SharedArrayBuffer<"u"&&e instanceof SharedArrayBuffer)return e.slice(0);const t=Object.getPrototypeOf(e);if(t==null)return Object.assign(Object.create(t),e);const n=t.constructor;if(e instanceof Date||e instanceof Map||e instanceof Set)return new n(e);if(e instanceof RegExp){const r=new n(e);return r.lastIndex=e.lastIndex,r}if(e instanceof DataView)return new n(e.buffer.slice(0));if(e instanceof Error){let r;return e instanceof AggregateError?r=new n(e.errors,e.message,{cause:e.cause}):r=new n(e.message,{cause:e.cause}),r.stack=e.stack,Object.assign(r,e),r}return typeof File<"u"&&e instanceof File?new n([e],e.name,{type:e.type,lastModified:e.lastModified}):typeof e=="object"?Object.assign(Object.create(t),e):e}function Rf(e){return typeof F_.Buffer<"u"&&F_.Buffer.isBuffer(e)}function Nf(e){return Object.getOwnPropertySymbols(e).filter(t=>Object.prototype.propertyIsEnumerable.call(e,t))}function oc(e){return e==null?e===void 0?"[object Undefined]":"[object Null]":Object.prototype.toString.call(e)}const k$="[object RegExp]",o1="[object String]",l1="[object Number]",i1="[object Boolean]",w$="[object Arguments]",$$="[object Symbol]",C$="[object Date]",S$="[object Map]",E$="[object Set]",O$="[object Array]",N3="[object Function]",T$="[object ArrayBuffer]",ef="[object Object]",L3="[object Error]",A$="[object DataView]",P$="[object Uint8Array]",M$="[object Uint8ClampedArray]",D$="[object Uint16Array]",V$="[object Uint32Array]",F3="[object BigUint64Array]",I$="[object Int8Array]",R$="[object Int16Array]",N$="[object Int32Array]",B3="[object BigInt64Array]",L$="[object Float32Array]",F$="[object Float64Array]";function q3(e,t){return Vl(e,void 0,e,new Map,t)}function Vl(e,t,n,r=new Map,s=void 0){const o=s==null?void 0:s(e,t,n,r);if(o!==void 0)return o;if(r1(e))return e;if(r.has(e))return r.get(e);if(Array.isArray(e)){const l=new Array(e.length);r.set(e,l);for(let a=0;amu(f,h,void 0,e,t,n,r));if(p===-1)return!1;c.splice(p,1)}return!0}case O$:case P$:case M$:case D$:case V$:case F3:case I$:case R$:case N$:case B3:case L$:case F$:if(Rf(e)!==Rf(t)||e.length!==t.length)return!1;for(let u=0;u=0}const z3={"&":"&","<":"<",">":">",'"':""","'":"'"};function K3(e){return e.replace(/[&<>"']/g,t=>z3[t])}function W3(e){return e!=null&&typeof e!="function"&&H3(e.length)}function q$(e){return typeof e=="symbol"||e instanceof Symbol}function U$(e){return e==null?"":j$(e)}function j$(e){if(typeof e=="string")return e;if(Array.isArray(e))return e.map(j$).join(",");if(q$(e))return e.toString();const t=e+"";return t==="0"&&Object.is(Number(e),-0)?"-0":t}function Tm(e){var t;return typeof e=="string"||typeof e=="symbol"?e:Object.is((t=e==null?void 0:e.valueOf)==null?void 0:t.call(e),-0)?"-0":String(e)}function Am(e){if(Array.isArray(e))return e.map(Tm);if(typeof e=="symbol")return[e];e=U$(e);const t=[],n=e.length;if(n===0)return t;let r=0,s="",o="",l=!1,a=!1;const u=/^-?\d+(?:\.\d+)?$/;for(e.charCodeAt(0)===46&&t.push("");r{if(typeof e=="object"){if(oc(e)==="[object Object]"&&typeof e.constructor!="function"){const l={};return o.set(e,l),Jr(l,e,s,o),l}switch(Object.prototype.toString.call(e)){case l1:case o1:case i1:{const l=new e.constructor(e==null?void 0:e.valueOf());return Jr(l,e),l}case w$:{const l={};return Jr(l,e),l.length=e.length,l[Symbol.iterator]=e[Symbol.iterator],l}default:return}}})}function U_(e){return Y3(e)}function av(e){return e!==null&&typeof e=="object"&&oc(e)==="[object Arguments]"}const X3=/^(?:0|[1-9]\d*)$/;function z$(e,t=Number.MAX_SAFE_INTEGER){switch(typeof e){case"number":return Number.isInteger(e)&&e>=0&&e{const r=e[t];(!(Object.hasOwn(e,t)&&B$(r,n))||n===void 0&&!(t in e))&&(e[t]=n)};function rM(e){return e==="__proto__"||e==="constructor"||e==="prototype"}function sM(e,t,n,r){if(e==null&&!q_(e))return e;let s;tM(t,e)?s=[t]:Array.isArray(t)?s=t:s=Am(t);const o=n(qt(e,s));let l=e;for(let a=0;an,()=>{})}function oM(e,t=0,n={}){typeof n!="object"&&(n={});const{leading:r=!1,trailing:s=!0,maxWait:o}=n,l=Array(2);r&&(l[0]="leading"),s&&(l[1]="trailing");let a,u=null;const c=I3(function(...p){a=e.apply(this,p),u=null},t,{edges:l}),d=function(...p){return o!=null&&(u===null&&(u=Date.now()),Date.now()-u>=o)?((r||s)&&(a=e.apply(this,p)),u=Date.now(),c.cancel(),c.schedule(),a):(c.apply(this,p),a)},f=()=>(c.flush(),a);return d.cancel=c.cancel,d.flush=f,d}function lM(e,...t){const n=t.slice(0,-1),r=t[t.length-1];let s=e;for(let o=0;otypeof File<"u"&&e instanceof File||e instanceof Blob||typeof FileList<"u"&&e instanceof FileList&&e.length>0,Pm=e=>e instanceof FormData?!0:a1(e)||typeof e=="object"&&e!==null&&Object.values(e).some(t=>Pm(t));let Bf=class extends Error{constructor(n){super(`HTTP error ${n.status}`);Re(this,"response");this.name="HttpResponseError",this.response=n}},G$=class extends Error{constructor(t="Request was cancelled"){super(t),this.name="HttpCancelledError"}},iM=class extends Error{constructor(t="Network error"){super(t),this.name="HttpNetworkError"}};function aM(e){const t=new URLSearchParams;return Object.entries(e).forEach(([n,r])=>{r!=null&&(Array.isArray(r)?r.forEach(s=>t.append(`${n}[]`,String(s))):typeof r=="object"?t.append(n,JSON.stringify(r)):t.append(n,String(r)))}),t.toString()}function uM(e,t,n){if(t&&!e.startsWith("http://")&&!e.startsWith("https://")&&(e=t.replace(/\/$/,"")+"/"+e.replace(/^\//,"")),n&&Object.keys(n).length>0){const r=aM(n);r&&(e+=(e.includes("?")?"&":"?")+r)}return e}function cM(){var e,t,n,r;return typeof window>"u"?null:((r=(n=(t=(e=window.axios)==null?void 0:e.defaults)==null?void 0:t.headers)==null?void 0:n.common)==null?void 0:r["X-Requested-With"])??null}function J$(e,t=new FormData,n=null){for(const r in e)Object.prototype.hasOwnProperty.call(e,r)&&Y$(t,n?`${n}[${r}]`:r,e[r]);return t}function Y$(e,t,n){if(Array.isArray(n))return n.forEach((r,s)=>Y$(e,`${t}[${s}]`,r));if(n instanceof Date)return e.append(t,n.toISOString());if(typeof File<"u"&&n instanceof File)return e.append(t,n,n.name);if(n instanceof Blob)return e.append(t,n);if(typeof n=="boolean")return e.append(t,n?"1":"0");if(typeof n=="string")return e.append(t,n);if(typeof n=="number")return e.append(t,`${n}`);if(n==null)return e.append(t,"");J$(n,e,t)}function dM(e,t){var n;if(e!=null)return e instanceof FormData?e:typeof e=="object"&&Pm(e)?J$(e):typeof e=="object"||(n=t["Content-Type"])!=null&&n.includes("application/json")?JSON.stringify(e):String(e)}function fM(e){const t={};return e.forEach((n,r)=>{t[r.toLowerCase()]=n}),t}function pM(e={}){let t=e.xsrfCookieName??"XSRF-TOKEN",n=e.xsrfHeaderName??"X-XSRF-TOKEN";function r(){if(typeof document>"u")return null;const s=document.cookie.match(new RegExp("(^|;\\s*)"+t+"=([^;]*)"));return s?decodeURIComponent(s[2]):null}return{setXsrfCookieName(s){t=s},setXsrfHeaderName(s){n=s},async request(s){const o=uM(s.url,s.baseURL,s.params),l=s.method.toUpperCase(),a={},u=cM();u&&(a["X-Requested-With"]=u),s.data!==void 0&&!["GET","DELETE"].includes(l)&&!(s.data instanceof FormData)&&!Pm(s.data)&&(a["Content-Type"]="application/json"),s.headers&&Object.entries(s.headers).forEach(([b,x])=>{x!==void 0&&(a[b]=String(x))});const c=r();c&&!["GET","HEAD","OPTIONS"].includes(l)&&(a[n]=c);let d=s.signal,f;const p=s.timeout??3e4;if(p>0&&!d){const b=new AbortController;d=b.signal,f=setTimeout(()=>b.abort(),p)}const h=["GET","DELETE"].includes(l)?void 0:dM(s.data,a);h instanceof FormData&&delete a["Content-Type"];try{const b=await fetch(o,{method:l,headers:a,body:h,signal:d,credentials:s.credentials??"same-origin"});f&&clearTimeout(f);let x;const w=b.headers.get("content-type");w!=null&&w.includes("application/json")?x=await b.json():x=await b.text();const k={status:b.status,data:x,headers:fM(b.headers)};if(!b.ok)throw new Bf(k);return k}catch(b){throw f&&clearTimeout(f),b instanceof Bf?b:b instanceof DOMException&&b.name==="AbortError"?new G$:b instanceof TypeError?new iM(b.message):b}}}}const cv=pM();let u1=cv,c1,X$,Q$="same-origin",Z$=e=>`${e.method}:${e.baseURL??c1??""}${e.url}`,eC=e=>e.status===204&&e.headers["precognition-success"]==="true";const qf={},Yn={get:(e,t={},n={})=>Xa(Ya("get",e,t,n)),post:(e,t={},n={})=>Xa(Ya("post",e,t,n)),patch:(e,t={},n={})=>Xa(Ya("patch",e,t,n)),put:(e,t={},n={})=>Xa(Ya("put",e,t,n)),delete:(e,t={},n={})=>Xa(Ya("delete",e,t,n)),useHttpClient(e){return u1=e,Yn},withBaseURL(e){return c1=e,Yn},withTimeout(e){return X$=e,Yn},withCredentials(e){return Q$=typeof e=="string"?e:e?"include":"omit",Yn},fingerprintRequestsUsing(e){return Z$=e===null?()=>null:e,Yn},determineSuccessUsing(e){return eC=e,Yn},withXsrfCookieName(e){return cv.setXsrfCookieName(e),Yn},withXsrfHeaderName(e){return cv.setXsrfHeaderName(e),Yn}},Ya=(e,t,n,r)=>({url:t,method:e,...r,...["get","delete"].includes(e)?{params:Ff({},n,r==null?void 0:r.params)}:{data:Ff({},n,r==null?void 0:r.data)}}),Xa=(e={})=>{const t=[mM,gM,vM].reduce((n,r)=>r(n),e);return(t.onBefore??(()=>!0))()===!1?Promise.resolve(null):((t.onStart??(()=>null))(),u1.request({method:t.method,url:t.url,baseURL:t.baseURL??c1,data:t.data,params:t.params,headers:t.headers,signal:t.signal,timeout:t.timeout,credentials:Q$}).then(async n=>{t.precognitive&&j_(n);const r=n.status;let s=n;return t.precognitive&&t.onPrecognitionSuccess&&eC(n)&&(s=await Promise.resolve(t.onPrecognitionSuccess(n)??s)),t.onSuccess&&hM(r)&&(s=await Promise.resolve(t.onSuccess(s)??s)),(H_(t,r)??(l=>l))(s)??s},n=>{if(yM(n))return Promise.reject(n);const r=n;return t.precognitive&&j_(r.response),(H_(t,r.response.status)??((o,l)=>Promise.reject(l)))(r.response,r)}).finally(t.onFinish??(()=>null)))},mM=e=>{const t=e.only??e.validate;return{...e,timeout:e.timeout??X$,precognitive:e.precognitive!==!1,fingerprint:typeof e.fingerprint>"u"?Z$(e,u1):e.fingerprint,headers:{...e.headers,Accept:"application/json","Content-Type":bM(e),...e.precognitive!==!1?{Precognition:!0}:{},...t?{"Precognition-Validate-Only":Array.from(t).join()}:{}}}},hM=e=>e>=200&&e<300,gM=e=>{var t;return typeof e.fingerprint!="string"||((t=qf[e.fingerprint])==null||t.abort(),delete qf[e.fingerprint]),e},vM=e=>typeof e.fingerprint!="string"||e.signal||!e.precognitive?e:(qf[e.fingerprint]=new AbortController,{...e,signal:qf[e.fingerprint].signal}),j_=e=>{var t;if(((t=e.headers)==null?void 0:t.precognition)!=="true")throw Error("Did not receive a Precognition response. Ensure you have the Precognition middleware in place for the route.")},yM=e=>{var t;return!(e instanceof Bf)||typeof((t=e.response)==null?void 0:t.status)!="number"},H_=(e,t)=>({401:e.onUnauthorized,403:e.onForbidden,404:e.onNotFound,409:e.onConflict,422:e.onValidationError,423:e.onLocked})[t],bM=e=>{var t,n,r;return((t=e.headers)==null?void 0:t["Content-Type"])??((n=e.headers)==null?void 0:n["Content-type"])??((r=e.headers)==null?void 0:r["content-type"])??(Pm(e.data)?"multipart/form-data":"application/json")},_M=(e,t)=>{if(!e.includes("*"))return[e];const n=e.split(".");let r=[""];for(const s of n)if(s==="*"){const o=[];for(const l of r){const a=l?qt(t,l):t;if(Array.isArray(a))for(let u=0;uo?`${o}.${s}`:s);return r},xM=(e,t)=>t.includes("*")?new RegExp("^"+t.replace(/\./g,"\\.").replace(/\*/g,"[^.]+")+"$").test(e):e===t,z_=(e,t)=>Object.fromEntries(Object.entries(e).filter(([n])=>!t.some(r=>xM(n,r)))),kM=(e,t={})=>{const n={errorsChanged:[],touchedChanged:[],validatingChanged:[],validatedChanged:[]};let r=!1,s=!1;const o=L=>L!==s?(s=L,n.validatingChanged):[];let l=[];const a=L=>{const F=[...new Set(L)];return l.length!==F.length||!F.every(N=>l.includes(N))?(l=F,n.validatedChanged):[]},u=()=>l.filter(L=>typeof f[L]>"u");let c=[];const d=L=>{const F=[...new Set(L)];return c.length!==F.length||!F.every(N=>c.includes(N))?(c=F,n.touchedChanged):[]};let f={};const p=L=>{const F=wM(L);return ts(f,F)?[]:(f=F,n.errorsChanged)},h=L=>{const F={...f};return delete F[Eu(L)],p(F)},b=()=>Object.keys(f).length>0;let x=1500;const w=L=>{x=L,O.cancel(),O=T()};let k=t,C=null,S=[],E=null;const T=()=>oM(L=>{e({get:(F,N={},j={})=>Yn.get(F,M(N),P(j,L,N)),post:(F,N={},j={})=>Yn.post(F,M(N),P(j,L,N)),patch:(F,N={},j={})=>Yn.patch(F,M(N),P(j,L,N)),put:(F,N={},j={})=>Yn.put(F,M(N),P(j,L,N)),delete:(F,N={},j={})=>Yn.delete(F,M(N),P(j,L,N))}).catch(F=>{var N;return F instanceof G$||F instanceof Bf&&((N=F.response)==null?void 0:N.status)===422?null:Promise.reject(F)})},x,{leading:!0,trailing:!0});let O=T();const P=(L,F,N={})=>{const j={...L,...F},q=Array.from(j.only??j.validate??c);return{...F,...Ff({},L,F),only:q,timeout:j.timeout??5e3,onValidationError:(W,X)=>([...a([...l,...q]),...p(Ff(z_({...f},q),W.data.errors))].forEach(ee=>ee()),j.onValidationError?j.onValidationError(W,X):Promise.reject(X)),onSuccess:W=>(a([...l,...q]).forEach(X=>X()),j.onSuccess?j.onSuccess(W):W),onPrecognitionSuccess:W=>([...a([...l,...q]),...p(z_({...f},q))].forEach(X=>X()),j.onPrecognitionSuccess?j.onPrecognitionSuccess(W):W),onBefore:()=>{const W=c.some(ce=>ce.includes("*")),X=W?[...new Set(c.flatMap(ce=>_M(ce,N)))]:c;return j.onBeforeValidation&&j.onBeforeValidation({data:N,touched:X},{data:k,touched:S})===!1||(j.onBefore||(()=>!0))()===!1?!1:(W&&d(X).forEach(ce=>ce()),E=c,C=N,!0)},onStart:()=>{o(!0).forEach(W=>W()),(j.onStart??(()=>null))()},onFinish:()=>{o(!1).forEach(W=>W()),S=E,k=C,E=C=null,(j.onFinish??(()=>null))()}}},I=(L,F,N)=>{if(typeof L>"u"){const j=Array.from((N==null?void 0:N.only)??(N==null?void 0:N.validate)??[]);d([...c,...j]).forEach(q=>q()),O(N??{});return}if(a1(F)&&!r){console.warn('Precognition file validation is not active. Call the "validateFiles" function on your form to enable it.');return}L=Eu(L),(L.includes("*")||qt(k,L)!==F)&&(d([L,...c]).forEach(j=>j()),O(N??{}))},M=L=>r===!1?dv(L):L,D={touched:()=>c,validate(L,F,N){return typeof L=="object"&&!("target"in L)&&(N=L,L=F=void 0),I(L,F,N),D},touch(L){const F=Array.isArray(L)?L:[Eu(L)];return d([...c,...F]).forEach(N=>N()),D},validating:()=>s,valid:u,errors:()=>f,hasErrors:b,setErrors(L){return p(L).forEach(F=>F()),D},forgetError(L){return h(L).forEach(F=>F()),D},defaults(L){return t=L,k=L,D},reset(...L){if(L.length===0)d([]).forEach(F=>F());else{const F=[...c];L.forEach(N=>{F.includes(N)&&F.splice(F.indexOf(N),1),fr(k,N,qt(t,N))}),d(F).forEach(N=>N())}return D},setTimeout(L){return w(L),D},on(L,F){return n[L].push(F),D},validateFiles(){return r=!0,D},withoutFileValidation(){return r=!1,D}};return D},tC=e=>Object.keys(e).reduce((t,n)=>({...t,[n]:Array.isArray(e[n])?e[n][0]:e[n]}),{}),wM=e=>Object.keys(e).reduce((t,n)=>({...t,[n]:typeof e[n]=="string"?[e[n]]:e[n]}),{}),Eu=e=>typeof e!="string"?e.target.name:e,dv=e=>{const t={...e};return Object.keys(t).forEach(n=>{const r=t[n];if(r!==null){if(a1(r)){delete t[n];return}if(Array.isArray(r)){t[n]=Object.values(dv({...r}));return}if(typeof r=="object"){t[n]=dv(t[n]);return}}}),t};var $M=class{constructor(e){Re(this,"config",{});Re(this,"defaults");this.defaults=e}extend(e){return e&&(this.defaults={...this.defaults,...e}),this}replace(e){this.config=e}get(e){return K$(this.config,e)?qt(this.config,e):qt(this.defaults,e)}set(e,t){typeof e=="string"?fr(this.config,e,t):Object.entries(e).forEach(([n,r])=>{fr(this.config,n,r)})}},ei=new $M({form:{recentlySuccessfulDuration:2e3,forceIndicesArrayFormatInFormData:!0,withAllErrors:!1},prefetch:{cacheFor:3e4,hoverDelay:75}});function lc(e,t){let n;return function(...r){clearTimeout(n),n=setTimeout(()=>e.apply(this,r),t)}}function rr(e,t){return document.dispatchEvent(new CustomEvent(`inertia:${e}`,t))}var K_=e=>rr("before",{cancelable:!0,detail:{visit:e}}),CM=(e,{page:t,visitId:n}={})=>rr("error",{detail:{errors:e,page:t,visitId:n}}),SM=e=>rr("networkError",{cancelable:!0,detail:{error:e}}),EM=e=>rr("finish",{detail:{visit:e}}),W_=e=>rr("httpException",{cancelable:!0,detail:{response:e}}),OM=e=>rr("beforeUpdate",{detail:{page:e}}),Uf=(e,{cached:t=!1,visitId:n}={})=>rr("navigate",{detail:{page:e,cached:t,visitId:n}}),TM=(e,{replace:t,visitId:n})=>rr("clientVisit",{detail:{page:e,replace:t,visitId:n}}),AM=e=>rr("progress",{detail:{progress:e}}),PM=e=>rr("start",{detail:{visit:e}}),MM=(e,{visitId:t}={})=>rr("success",{detail:{page:e,visitId:t}}),DM=(e,t)=>rr("prefetched",{detail:{fetchedAt:Date.now(),response:e,visit:t}}),VM=e=>rr("prefetching",{detail:{visit:e}}),jf=e=>rr("flash",{detail:{flash:e}}),IM=(e,t)=>rr("location",{cancelable:!0,detail:{url:e,versionChange:t}}),Hg,ar=(Hg=class{static set(e,t){typeof window<"u"&&window.sessionStorage.setItem(e,JSON.stringify(t))}static get(e){if(typeof window<"u")return JSON.parse(window.sessionStorage.getItem(e)||"null")}static merge(e,t){const n=this.get(e);n===null?this.set(e,t):this.set(e,{...n,...t})}static remove(e){typeof window<"u"&&window.sessionStorage.removeItem(e)}static removeNested(e,t){const n=this.get(e);n!==null&&(delete n[t],this.set(e,n))}static exists(e){try{return this.get(e)!==null}catch{return!1}}static clear(){typeof window<"u"&&window.sessionStorage.clear()}},Re(Hg,"locationVisitKey","inertiaLocationVisit"),Hg),RM=async e=>{if(typeof window>"u")throw new Error("Unable to encrypt history");const t=nC(),n=await rC(),r=await UM(n);if(!r)throw new Error("Unable to encrypt history");return await LM(t,r,e)},ua={key:"historyKey",iv:"historyIv"},NM=async e=>{const t=nC(),n=await rC();if(!n)throw new Error("Unable to decrypt history");return await FM(t,n,e)},LM=async(e,t,n)=>{if(typeof window>"u")throw new Error("Unable to encrypt history");if(typeof window.crypto.subtle>"u")return console.warn("Encryption is not supported in this environment. SSL is required."),Promise.resolve(n);const r=new TextEncoder,s=JSON.stringify(n),o=new Uint8Array(s.length*3),l=r.encodeInto(s,o);return window.crypto.subtle.encrypt({name:"AES-GCM",iv:e},t,o.subarray(0,l.written))},FM=async(e,t,n)=>{if(typeof window.crypto.subtle>"u")return console.warn("Decryption is not supported in this environment. SSL is required."),Promise.resolve(n);const r=await window.crypto.subtle.decrypt({name:"AES-GCM",iv:e},t,n);return JSON.parse(new TextDecoder().decode(r))},nC=()=>{const e=ar.get(ua.iv);if(e)return new Uint8Array(e);const t=window.crypto.getRandomValues(new Uint8Array(12));return ar.set(ua.iv,Array.from(t)),t},BM=async()=>typeof window.crypto.subtle>"u"?(console.warn("Encryption is not supported in this environment. SSL is required."),Promise.resolve(null)):window.crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),qM=async e=>{if(typeof window.crypto.subtle>"u")return console.warn("Encryption is not supported in this environment. SSL is required."),Promise.resolve();const t=await window.crypto.subtle.exportKey("raw",e);ar.set(ua.key,Array.from(new Uint8Array(t)))},UM=async e=>{if(e)return e;const t=await BM();return t?(await qM(t),t):null},rC=async()=>{const e=ar.get(ua.key);return e?await window.crypto.subtle.importKey("raw",new Uint8Array(e),{name:"AES-GCM",length:256},!0,["encrypt","decrypt"]):null},G_=e=>{const t={};for(const n of Object.keys(e))e[n]!==void 0&&(t[n]=e[n]);return t},sC=(e,t,n)=>{if(e===t)return!0;for(const r in e)if(!n.includes(r)&&e[r]!==t[r]&&!jM(e[r],t[r]))return!1;for(const r in t)if(!n.includes(r)&&!(r in e))return!1;return!0},jM=(e,t)=>{switch(typeof e){case"object":return sC(e,t,[]);case"function":return e.toString()===t.toString();default:return e===t}},HM=(e,t,n)=>{const r=Am(t);if(r.length===0)return e;const s=(o,l)=>{if(l===r.length)return n;const a=r[l],u=Array.isArray(o)?[...o]:o&&typeof o=="object"?{...o}:/^(?:0|[1-9]\d*)$/.test(a)?[]:{};return u[a]=s(o==null?void 0:o[a],l+1),u};return s(e,0)},zM={ms:1,s:1e3,m:1e3*60,h:1e3*60*60,d:1e3*60*60*24},J_=e=>{if(typeof e=="number")return e;for(const[t,n]of Object.entries(zM))if(e.endsWith(t))return parseFloat(e)*n;return parseInt(e)},KM=class{constructor(){Re(this,"cached",[]);Re(this,"inFlightRequests",[]);Re(this,"removalTimers",[]);Re(this,"currentUseId",null)}add(e,t,{cacheFor:n,cacheTags:r}){if(this.findInFlight(e))return Promise.resolve();const o=this.findCached(e);if(!e.fresh&&o&&o.staleTimestamp>Date.now())return Promise.resolve();const[l,a]=this.extractStaleValues(n),u=new Promise((c,d)=>{t({...e,onCancel:()=>{this.remove(e),e.onCancel(),d()},onError:f=>{this.remove(e),e.onError(f),d()},onPrefetching(f){e.onPrefetching(f)},onPrefetched(f,p){e.onPrefetched(f,p)},onPrefetchResponse(f){c(f)},onPrefetchError(f){hs.removeFromInFlight(e),d(f)}})}).then(c=>{this.remove(e);const d=c.getPageResponse();Ve.mergeOncePropsIntoResponse(d),this.cached.push({params:{...e},staleTimestamp:Date.now()+l,expiresAt:Date.now()+a,response:u,singleUse:a===0,timestamp:Date.now(),inFlight:!1,tags:Array.isArray(r)?r:[r]});const f=this.getShortestOncePropTtl(d);return this.scheduleForRemoval(e,f?Math.min(a,f):a),this.removeFromInFlight(e),c.handlePrefetch(),c});return this.inFlightRequests.push({params:{...e},response:u,staleTimestamp:null,inFlight:!0}),u}removeAll(){this.cached=[],this.removalTimers.forEach(e=>{clearTimeout(e.timer)}),this.removalTimers=[]}removeByTags(e){this.cached=this.cached.filter(t=>!t.tags.some(n=>e.includes(n)))}remove(e){this.cached=this.cached.filter(t=>!this.paramsAreEqual(t.params,e)),this.clearTimer(e)}removeFromInFlight(e){this.inFlightRequests=this.inFlightRequests.filter(t=>!this.paramsAreEqual(t.params,e))}extractStaleValues(e){const[t,n]=this.cacheForToStaleAndExpires(e);return[J_(t),J_(n)]}cacheForToStaleAndExpires(e){if(!Array.isArray(e))return[e,e];switch(e.length){case 0:return[0,0];case 1:return[e[0],e[0]];default:return[e[0],e[1]]}}clearTimer(e){const t=this.removalTimers.find(n=>this.paramsAreEqual(n.params,e));t&&(clearTimeout(t.timer),this.removalTimers=this.removalTimers.filter(n=>n!==t))}scheduleForRemoval(e,t){if(!(typeof window>"u")&&(this.clearTimer(e),t>0)){const n=window.setTimeout(()=>this.remove(e),t);this.removalTimers.push({params:e,timer:n})}}get(e){return this.findCached(e)||this.findInFlight(e)}use(e,t){const n=`${t.url.pathname}-${Date.now()}-${Math.random().toString(36).substring(7)}`;this.currentUseId=n;const r={...t,cached:!0};return e.response.then(s=>{if(this.currentUseId===n)return s.mergeParams({...r,onPrefetched:()=>{}}),this.removeSingleUseItems(t),s.handle()})}removeSingleUseItems(e){this.cached=this.cached.filter(t=>this.paramsAreEqual(t.params,e)?!t.singleUse:!0)}findCached(e){return this.cached.find(t=>this.paramsAreEqual(t.params,e))||null}findInFlight(e){return this.inFlightRequests.find(t=>this.paramsAreEqual(t.params,e))||null}withoutPurposePrefetchHeader(e){const t=Tt(e);return t.headers.Purpose==="prefetch"&&delete t.headers.Purpose,t}paramsAreEqual(e,t){return sC(this.withoutPurposePrefetchHeader(e),this.withoutPurposePrefetchHeader(t),["id","showProgress","replace","prefetch","preserveScroll","preserveState","onBefore","onBeforeUpdate","onStart","onProgress","onFinish","onCancel","onSuccess","onError","onFlash","onPrefetched","onCancelToken","onPrefetching","async","viewTransition","optimistic","component","pageProps","cached"])}updateCachedOncePropsFromCurrentPage(){this.cached.forEach(e=>{e.response.then(t=>{const n=t.getPageResponse();Ve.mergeOncePropsIntoResponse(n,{force:!0});for(const[l,a]of Object.entries(n.deferredProps??{})){const u=a.filter(c=>qt(n.props,c)===void 0);u.length>0?n.deferredProps[l]=u:delete n.deferredProps[l]}const r=this.getShortestOncePropTtl(n);if(r===null)return;const s=e.expiresAt-Date.now(),o=Math.min(s,r);o>0?this.scheduleForRemoval(e.params,o):this.remove(e.params)})})}getShortestOncePropTtl(e){const t=Object.values(e.onceProps??{}).map(n=>n.expiresAt).filter(n=>!!n);return t.length===0?null:Math.min(...t)-Date.now()}},hs=new KM,Mh=e=>{if(e.offsetParent===null)return!1;const t=e.getBoundingClientRect(),n=t.top=0,r=t.left=0;return n&&r},WM=e=>{const t=l=>{const a=window.getComputedStyle(l);return a.overflowY==="scroll"?!0:a.overflowY!=="auto"?!1:["visible","clip"].includes(a.overflowX)?!0:r(a.maxHeight,l.style.height)||s(l,"height")},n=l=>{const a=window.getComputedStyle(l);return a.overflowX==="scroll"?!0:a.overflowX!=="auto"?!1:["visible","clip"].includes(a.overflowY)?!0:r(a.maxWidth,l.style.width)||s(l,"width")},r=(l,a)=>!!(l&&l!=="none"&&l!=="0px"||a&&a!=="auto"&&a!=="0"),s=(l,a)=>{const u=l.parentElement;if(!u)return!1;const c=window.getComputedStyle(u);if(["flex","inline-flex"].includes(c.display)){const d=["column","column-reverse"].includes(c.flexDirection);return a==="height"?d:!d}return["grid","inline-grid"].includes(c.display)};let o=e==null?void 0:e.parentElement;for(;o;){const l=t(o)||n(o);if(window.getComputedStyle(o).display!=="contents"&&l)return o;o=o.parentElement}return null},oC=(e,t)=>{if(!t)return e.filter(o=>Mh(o));const n=e.indexOf(t),r=[],s=[];for(let o=n;o>=0;o--){const l=e[o];if(Mh(l))r.push(l);else break}for(let o=n+1;o{window.requestAnimationFrame(()=>{t>1?Ou(e,t-1):e()})},GM=e=>{if(typeof window>"u")return null;const t=document.querySelector(`script[data-page="${e}"][type="application/json"]`);return t!=null&&t.textContent?JSON.parse(t.textContent):null},hu=typeof window>"u",JM=!hu&&/Firefox/i.test(window.navigator.userAgent),ur=class{static save(){xt.saveScrollPositions(this.getScrollRegions())}static getScrollRegions(){return Array.from(this.regions()).map(e=>({top:e.scrollTop,left:e.scrollLeft}))}static regions(){return document.querySelectorAll("[scroll-region]")}static scrollToTop(){if(JM&&getComputedStyle(document.documentElement).scrollBehavior==="smooth")return Ou(()=>window.scrollTo(0,0),2);window.scrollTo(0,0)}static reset(){(hu?null:window.location.hash)||this.scrollToTop(),this.regions().forEach(t=>{typeof t.scrollTo=="function"?t.scrollTo(0,0):(t.scrollTop=0,t.scrollLeft=0)}),this.save(),this.scrollToAnchor()}static scrollToAnchor(){const e=hu?null:window.location.hash;e&&setTimeout(()=>{const t=document.getElementById(e.slice(1));t?t.scrollIntoView():this.scrollToTop()})}static restore(e){hu||window.requestAnimationFrame(()=>{this.restoreDocument(),this.restoreScrollRegions(e)})}static restoreScrollRegions(e){hu||this.regions().forEach((t,n)=>{const r=e[n];r&&(typeof t.scrollTo=="function"?t.scrollTo(r.left,r.top):(t.scrollTop=r.top,t.scrollLeft=r.left))})}static restoreDocument(){const e=xt.getDocumentScrollPosition();window.scrollTo(e.left,e.top)}static onScroll(e){const t=e.target;typeof t.hasAttribute=="function"&&t.hasAttribute("scroll-region")&&this.save()}static onWindowScroll(){xt.saveDocumentScrollPosition({top:window.scrollY,left:window.scrollX})}},d1=e=>typeof File<"u"&&e instanceof File||e instanceof Blob||typeof FileList<"u"&&e instanceof FileList&&e.length>0;function Hf(e){return d1(e)||e instanceof FormData&&Array.from(e.values()).some(t=>Hf(t))||typeof e=="object"&&e!==null&&Object.values(e).some(t=>Hf(t))}var fv=e=>e instanceof FormData;function f1(e,t=new FormData,n=null,r="brackets"){e=e||{};for(const s in e)Object.prototype.hasOwnProperty.call(e,s)&&iC(t,lC(n,s,"indices"),e[s],r);return t}function lC(e,t,n){return e?n==="brackets"?`${e}[]`:`${e}[${t}]`:t}function iC(e,t,n,r){if(Array.isArray(n))return Array.from(n.keys()).forEach(s=>iC(e,lC(t,s.toString(),r),n[s],r));if(n instanceof Date)return e.append(t,n.toISOString());if(n instanceof File)return e.append(t,n,n.name);if(n instanceof Blob)return e.append(t,n);if(typeof n=="boolean")return e.append(t,n?"1":"0");if(typeof n=="string")return e.append(t,n);if(typeof n=="number")return e.append(t,`${n}`);if(n==null)return e.append(t,"");f1(n,e,t,r)}function YM(e){return/\[\d+\]/.test(decodeURIComponent(e.search))}function XM(e){if(!e||e==="?")return{};const t={};return e.replace(/^\?/,"").split("&").filter(Boolean).forEach(n=>{const[r,s]=ZM(n);eD(t,Y_(r),Y_(s))}),t}function QM(e,t){const n=[];return pv(e,"",n,t),n.length?"?"+n.join("&"):""}function ZM(e){const t=e.indexOf("=");return t===-1?[e,""]:[e.substring(0,t),e.substring(t+1)]}function Y_(e){return decodeURIComponent(e.replace(/\+/g," "))}function eD(e,t,n){const r=tD(t);if(r.some(l=>l==="__proto__"))return;let s=e;for(;r.length>1;){const l=r.shift(),a=r[0]==="";(typeof s[l]!="object"||s[l]===null)&&(s[l]=a?[]:{}),s=s[l]}const o=r.shift();o===""&&Array.isArray(s)?s.push(n):s[o]=n}function tD(e){const t=[],n=e.split("[")[0];n&&t.push(n);let r;const s=/\[([^\]]*)\]/g;for(;(r=s.exec(e))!==null;)t.push(r[1]);return t}function pv(e,t,n,r){if(e!==void 0){if(e===null){n.push(`${t}=`);return}if(Array.isArray(e)){e.forEach((s,o)=>{const l=r==="indices"?`${t}[${o}]`:`${t}[]`;pv(s,l,n,r)});return}if(typeof e=="object"){Object.keys(e).forEach(s=>{pv(e[s],t?`${t}[${s}]`:s,n,r)});return}n.push(`${t}=${encodeURIComponent(String(e))}`)}}function Lr(e){return new URL(e.toString(),typeof window>"u"?void 0:window.location.toString())}var nD=(e,t,n,r,s)=>{let o=typeof e=="string"?Lr(e):e;if((Hf(t)||r)&&!fv(t)&&(ei.get("form.forceIndicesArrayFormatInFormData")&&(s="indices"),t=f1(t,new FormData,null,s)),fv(t))return[o,t];const[l,a]=Bc(n,o,t,s);return[Lr(l),a]};function Bc(e,t,n,r="brackets"){const s=e==="get"&&!fv(n)&&Object.keys(n).length>0,o=uC(t.toString()),l=o||t.toString().startsWith("/")||t.toString()==="",a=!l&&!t.toString().startsWith("#")&&!t.toString().startsWith("?"),u=/^[.]{1,2}([/]|$)/.test(t.toString()),c=t.toString().includes("?")||s,d=t.toString().includes("#"),f=new URL(t.toString(),typeof window>"u"?"http://localhost":window.location.toString());if(s){const p=YM(f)?"indices":r;f.search=QM({...XM(f.search),...n},p)}return[[o?`${f.protocol}//${f.host}`:"",l?f.pathname:"",a?f.pathname.substring(u?0:1):"",c?f.search:"",d?f.hash:""].join(""),s?{}:n]}function zf(e){return e=new URL(e.href),e.hash="",e}var X_=(e,t)=>{e.hash&&!t.hash&&zf(e).href===t.href&&(t.hash=e.hash)},Kf=(e,t)=>zf(e).href===zf(t).href,mv=(e,t)=>e.origin===t.origin&&e.pathname===t.pathname;function Qr(e){return e!==null&&typeof e=="object"&&e!==void 0&&"url"in e&&"method"in e}function aC(e){return e.component?typeof e.component!="string"?(console.error(`The "component" property on the URL method pair received multiple components (${Object.keys(e.component).join(", ")}), but only a single component string is supported for instant visits. Use the withComponent() method to specify which component to use.`),null):e.component:null}function uC(e){return/^([a-z][a-z0-9+.-]*:)?\/\/[^/]/i.test(e)}function rD(e,t){const n=typeof e=="string"?Lr(e):e;return t?`${n.protocol}//${n.host}${n.pathname}${n.search}${n.hash}`:`${n.pathname}${n.search}${n.hash}`}var sD=class{constructor(){Re(this,"page");Re(this,"swapComponent");Re(this,"resolveComponent");Re(this,"onFlashCallback");Re(this,"componentId",{});Re(this,"listeners",[]);Re(this,"isFirstPageLoad",!0);Re(this,"cleared",!1);Re(this,"pendingDeferredProps",null);Re(this,"historyQuotaExceeded",!1);Re(this,"optimisticBaseline",{});Re(this,"pendingOptimistics",[]);Re(this,"optimisticCounter",0)}init({initialPage:e,swapComponent:t,resolveComponent:n,onFlash:r}){return this.page={...e,flash:e.flash??{},rescuedProps:e.rescuedProps??[]},this.swapComponent=t,this.resolveComponent=n,this.onFlashCallback=r,ws.on("historyQuotaExceeded",()=>{this.historyQuotaExceeded=!0}),this}set(e,{replace:t=!1,preserveScroll:n=!1,preserveState:r=!1,viewTransition:s=!1,cached:o=!1,initialRender:l=!1,visitId:a}={}){Object.keys(e.deferredProps||{}).length&&(this.pendingDeferredProps={deferredProps:e.deferredProps,component:e.component,url:e.url},e.initialDeferredProps===void 0&&(e.initialDeferredProps=e.deferredProps)),this.componentId={};const u=this.componentId;return e.clearHistory&&xt.clear(),this.resolve(e.component,e).then(c=>{if(u!==this.componentId)return;e.rememberedState??(e.rememberedState={});const d=typeof window>"u",f=d?new URL(e.url):window.location,p=!d&&n?ur.getScrollRegions():[];t=t||Kf(Lr(e.url),f);const h={...e,flash:{}};return new Promise(b=>t?xt.replaceState(h,b):xt.pushState(h,b)).then(()=>{const b=!this.isTheSame(e);if(!b&&Object.keys(e.props.errors||{}).length>0&&(s=!1),this.page=e,this.cleared=!1,this.hasOnceProps()&&hs.updateCachedOncePropsFromCurrentPage(),b&&this.fireEventsFor("newComponent"),this.isFirstPageLoad&&this.fireEventsFor("firstLoad"),this.isFirstPageLoad=!1,this.historyQuotaExceeded){this.historyQuotaExceeded=!1;return}return this.swap({component:c,page:e,preserveState:r,viewTransition:s,initialRender:l}).then(()=>{n?window.requestAnimationFrame(()=>ur.restoreScrollRegions(p)):ur.reset(),this.pendingDeferredProps&&this.pendingDeferredProps.component===e.component&&this.pendingDeferredProps.url===e.url&&ws.fireInternalEvent("loadDeferredProps",this.pendingDeferredProps.deferredProps),this.pendingDeferredProps=null,t||Uf(e,{cached:o,visitId:a})})})})}setQuietly(e,{preserveState:t=!1}={}){return this.resolve(e.component,e).then(n=>(this.page=e,this.cleared=!1,xt.setCurrent(e),this.swap({component:n,page:e,preserveState:t,viewTransition:!1})))}clear(){this.cleared=!0}isCleared(){return this.cleared}get(){return this.page}getWithoutFlashData(){return{...this.page,flash:{}}}hasOnceProps(){return Object.keys(this.page.onceProps??{}).length>0}merge(e){this.page={...this.page,...e}}setPropsQuietly(e){return this.page={...this.page,props:e},this.resolve(this.page.component,this.page).then(t=>this.swap({component:t,page:this.page,preserveState:!0,viewTransition:!1}))}setFlash(e){var t;this.page={...this.page,flash:e},(t=this.onFlashCallback)==null||t.call(this,e)}setUrlHash(e){this.page.url.includes(e)||(this.page.url+=e)}remember(e){this.page.rememberedState=e}swap({component:e,page:t,preserveState:n,viewTransition:r,initialRender:s=!1}){const o=()=>this.swapComponent({component:e,page:t,preserveState:n,initialRender:s});if(!r||!(document!=null&&document.startViewTransition)||document.visibilityState==="hidden")return o();const l=typeof r=="boolean"?()=>null:r;return new Promise(a=>{const u=document.startViewTransition(()=>o().then(a));u.ready.catch(()=>{}),l(u)})}resolve(e,t){return Promise.resolve(this.resolveComponent(e,t))}nextOptimisticId(){return++this.optimisticCounter}setBaseline(e,t){e in this.optimisticBaseline||(this.optimisticBaseline[e]=t)}updateBaseline(e,t){e in this.optimisticBaseline&&(this.optimisticBaseline[e]=t)}hasBaseline(e){return e in this.optimisticBaseline}registerOptimistic(e,t){this.pendingOptimistics.push({id:e,callback:t})}unregisterOptimistic(e){this.pendingOptimistics=this.pendingOptimistics.filter(t=>t.id!==e)}replayOptimistics(){const e=Object.keys(this.optimisticBaseline);if(e.length===0)return{};const t=Tt(this.page.props);for(const r of e)t[r]=Tt(this.optimisticBaseline[r]);for(const{callback:r}of this.pendingOptimistics){const s=r(Tt(t));s&&Object.assign(t,s)}const n={};for(const r of e)n[r]=t[r];return n}pendingOptimisticCount(){return this.pendingOptimistics.length}clearOptimisticState(){this.optimisticBaseline={},this.pendingOptimistics=[]}isTheSame(e){return this.page.component===e.component}on(e,t){return this.listeners.push({event:e,callback:t}),()=>{this.listeners=this.listeners.filter(n=>n.event!==e&&n.callback!==t)}}fireEventsFor(e){this.listeners.filter(t=>t.event===e).forEach(t=>t.callback())}mergeOncePropsIntoResponse(e,{force:t=!1}={}){Object.entries(e.onceProps??{}).forEach(([n,r])=>{var o;const s=(o=this.page.onceProps)==null?void 0:o[n];s!==void 0&&(t||qt(e.props,r.prop)===void 0)&&(fr(e.props,r.prop,qt(this.page.props,s.prop)),e.onceProps[n].expiresAt=s.expiresAt)})}},Ve=new sD,Mm=class{constructor(){Re(this,"items",[]);Re(this,"processingPromise",null)}add(e){return this.items.push(e),this.process()}process(){return this.processingPromise??(this.processingPromise=this.processNext().finally(()=>{this.processingPromise=null})),this.processingPromise}processNext(){const e=this.items.shift();return e?Promise.resolve(e()).then(()=>this.processNext()):Promise.resolve()}},Mi=typeof window>"u",Qa=new Mm,Q_=!Mi&&/CriOS/.test(window.navigator.userAgent),oD=class{constructor(){Re(this,"rememberedState","rememberedState");Re(this,"scrollRegions","scrollRegions");Re(this,"preserveUrl",!1);Re(this,"current",{});Re(this,"initialState",null)}remember(e,t){var n;this.replaceState({...Ve.getWithoutFlashData(),rememberedState:{...((n=Ve.get())==null?void 0:n.rememberedState)??{},[t]:e}})}restore(e){var t,n,r,s;if(!Mi)return((t=this.current[this.rememberedState])==null?void 0:t[e])!==void 0?(n=this.current[this.rememberedState])==null?void 0:n[e]:(s=(r=this.initialState)==null?void 0:r[this.rememberedState])==null?void 0:s[e]}pushState(e,t=null){if(!Mi){if(this.preserveUrl){t&&t();return}this.current=e,Qa.add(()=>this.getPageData(e).then(n=>{const r=()=>this.doPushState({page:n},e.url).then(()=>t==null?void 0:t());return Q_?new Promise(s=>{setTimeout(()=>r().then(s))}):r()}))}}clonePageProps(e){try{return structuredClone(e.props),e}catch{return{...e,props:Tt(e.props)}}}getPageData(e){const t=this.clonePageProps(e);return new Promise(n=>e.encryptHistory?RM(t).then(n):n(t))}processQueue(){return Qa.process()}decrypt(e=null){var n;if(Mi)return Promise.resolve(e??Ve.get());const t=e??((n=window.history.state)==null?void 0:n.page);return this.decryptPageData(t).then(r=>{if(!r)throw new Error("Unable to decrypt history");return this.initialState===null?this.initialState=r??void 0:this.current=r??{},r})}decryptPageData(e){return e instanceof ArrayBuffer?NM(e):Promise.resolve(e)}saveScrollPositions(e){Qa.add(()=>Promise.resolve().then(()=>{var t;if((t=window.history.state)!=null&&t.page&&!ts(this.getScrollRegions(),e))return this.doReplaceState({page:window.history.state.page,scrollRegions:e})}))}saveDocumentScrollPosition(e){Qa.add(()=>Promise.resolve().then(()=>{var t;if((t=window.history.state)!=null&&t.page&&!ts(this.getDocumentScrollPosition(),e))return this.doReplaceState({page:window.history.state.page,documentScrollPosition:e})}))}getScrollRegions(){var e;return((e=window.history.state)==null?void 0:e.scrollRegions)||[]}getDocumentScrollPosition(){var e;return((e=window.history.state)==null?void 0:e.documentScrollPosition)||{top:0,left:0}}replaceState(e,t=null){if(ts(this.current,e)){t&&t();return}const{flash:n,...r}=e;if(Ve.merge(r),!Mi){if(this.preserveUrl){t&&t();return}this.current=e,Qa.add(()=>this.getPageData(e).then(s=>{const o=()=>this.doReplaceState({page:s},e.url).then(()=>t==null?void 0:t());return Q_?new Promise(l=>{setTimeout(()=>o().then(l))}):o()}))}}isHistoryThrottleError(e){return e instanceof Error&&e.name==="SecurityError"&&(e.message.includes("history.pushState")||e.message.includes("history.replaceState"))}isQuotaExceededError(e){return e instanceof Error&&e.name==="QuotaExceededError"}withThrottleProtection(e){return Promise.resolve().then(()=>{try{return e()}catch(t){if(!this.isHistoryThrottleError(t))throw t;console.error(t.message)}})}doReplaceState(e,t){return this.withThrottleProtection(()=>{var n,r;window.history.replaceState({...e,scrollRegions:e.scrollRegions??((n=window.history.state)==null?void 0:n.scrollRegions),documentScrollPosition:e.documentScrollPosition??((r=window.history.state)==null?void 0:r.documentScrollPosition)},"",t)})}doPushState(e,t){return this.withThrottleProtection(()=>{try{window.history.pushState(e,"",t)}catch(n){if(!this.isQuotaExceededError(n))throw n;ws.fireInternalEvent("historyQuotaExceeded",t)}})}getState(e,t){var n;return((n=this.current)==null?void 0:n[e])??t}deleteState(e){this.current[e]!==void 0&&(delete this.current[e],this.replaceState(this.current))}clearInitialState(e){this.initialState&&this.initialState[e]!==void 0&&delete this.initialState[e]}browserHasHistoryEntry(){var e;return!Mi&&!!((e=window.history.state)!=null&&e.page)}clear(){ar.remove(ua.key),ar.remove(ua.iv)}setCurrent(e){this.current=e}isValidState(e){return!!e.page}getAllState(){return this.current}};typeof window<"u"&&window.history.scrollRestoration&&(window.history.scrollRestoration="manual");var xt=new oD,lD=class{constructor(){Re(this,"internalListeners",[])}init(){typeof window<"u"&&(window.addEventListener("popstate",this.handlePopstateEvent.bind(this)),window.addEventListener("pageshow",this.handlePageshowEvent.bind(this)),window.addEventListener("scroll",lc(ur.onWindowScroll.bind(ur),100),!0)),typeof document<"u"&&document.addEventListener("scroll",lc(ur.onScroll.bind(ur),100),!0)}onGlobalEvent(e,t){const n=(r=>{const s=t(r);r.cancelable&&!r.defaultPrevented&&s===!1&&r.preventDefault()});return this.registerListener(`inertia:${e}`,n)}on(e,t){return this.internalListeners.push({event:e,listener:t}),()=>{this.internalListeners=this.internalListeners.filter(n=>n.listener!==t)}}onMissingHistoryItem(){Ve.clear(),this.fireInternalEvent("missingHistoryItem")}fireInternalEvent(e,...t){this.internalListeners.filter(n=>n.event===e).forEach(n=>n.listener(...t))}registerListener(e,t){return document.addEventListener(e,t),()=>document.removeEventListener(e,t)}handlePageshowEvent(e){e.persisted&&xt.decrypt().catch(()=>this.onMissingHistoryItem())}handlePopstateEvent(e){const t=e.state||null;if(t===null){const n=Lr(Ve.get().url);n.hash=window.location.hash,xt.replaceState({...Ve.getWithoutFlashData(),url:n.href}),ur.reset();return}if(!xt.isValidState(t))return this.onMissingHistoryItem();xt.decrypt(t.page).then(n=>{if(Ve.get().version!==n.version){this.onMissingHistoryItem();return}xe.cancelAll({prefetch:!1}),Ve.setQuietly(n,{preserveState:!1}).then(()=>{ur.restore(xt.getScrollRegions()),Uf(Ve.get());const r={},s=Ve.get().props;for(const[o,l]of Object.entries(n.initialDeferredProps??n.deferredProps??{})){const a=l.filter(u=>qt(s,u)===void 0);a.length>0&&(r[o]=a)}Object.keys(r).length>0&&this.fireInternalEvent("loadDeferredProps",r)})}).catch(()=>{this.onMissingHistoryItem()})}},ws=new lD,iD=class{constructor(){Re(this,"type");this.type=this.resolveType()}resolveType(){var t;if(typeof window>"u")return"navigate";const e=(t=window.performance)==null?void 0:t.getEntriesByType("navigation")[0];return(e==null?void 0:e.type)??"navigate"}get(){return this.type}isBackForward(){return this.type==="back_forward"}isReload(){return this.type==="reload"}},Dh=new iD;function nf(){const e=typeof window<"u"?window.crypto:void 0;if(e!=null&&e.randomUUID)return e.randomUUID();const t=()=>e!=null&&e.getRandomValues?e.getRandomValues(new Uint8Array(1))[0]:Math.floor(Math.random()*256);return"10000000-1000-4000-8000-100000000000".replace(/[018]/g,n=>(+n^t()&15>>+n/4).toString(16))}var aD=class{static handle(){this.clearRememberedStateOnReload(),[this.handleBackForward,this.handleLocation,this.handleDefault].find(t=>t.bind(this)())}static clearRememberedStateOnReload(){Dh.isReload()&&(xt.deleteState(xt.rememberedState),xt.clearInitialState(xt.rememberedState))}static handleBackForward(){if(!Dh.isBackForward()||!xt.browserHasHistoryEntry())return!1;const e=xt.getScrollRegions();return xt.decrypt().then(t=>{const n=nf();Ve.set(t,{preserveScroll:!0,preserveState:!0,visitId:n}).then(()=>{ur.restore(e),Uf(Ve.get(),{visitId:n})})}).catch(()=>{ws.onMissingHistoryItem()}),!0}static handleLocation(){if(!ar.exists(ar.locationVisitKey))return!1;const e=ar.get(ar.locationVisitKey)||{};return ar.remove(ar.locationVisitKey),typeof window<"u"&&Ve.setUrlHash(window.location.hash),xt.decrypt(Ve.get()).then(()=>{const t=nf(),n=xt.getState(xt.rememberedState,{}),r=xt.getScrollRegions();Ve.remember(n),Ve.set(Ve.get(),{preserveScroll:e.preserveScroll,preserveState:!0,initialRender:!0,visitId:t}).then(()=>{e.preserveScroll&&ur.restore(r),this.fireInitialEvents(t)})}).catch(()=>{ws.onMissingHistoryItem()}),!0}static handleDefault(){typeof window<"u"&&Ve.setUrlHash(window.location.hash);const e=nf();Ve.set(Ve.get(),{preserveScroll:!0,preserveState:!0,initialRender:!0,visitId:e}).then(()=>{Dh.isReload()?ur.restore(xt.getScrollRegions()):ur.scrollToAnchor(),this.fireInitialEvents(e)})}static fireInitialEvents(e){const t=Ve.get();Uf(t,{visitId:e}),Object.keys(t.flash).length>0&&queueMicrotask(()=>jf(t.flash))}},uD=class{constructor(e,t,n){Re(this,"intervalId",null);Re(this,"timeoutId",null);Re(this,"throttle",!1);Re(this,"keepAlive",!1);Re(this,"cb");Re(this,"interval");Re(this,"cbCount",0);Re(this,"mode");Re(this,"inFlight",!1);Re(this,"currentCancel",null);Re(this,"stopped",!0);Re(this,"instanceId",0);this.keepAlive=n.keepAlive??!1,this.mode=n.mode??"overlap",this.cb=t,this.interval=e,(n.autoStart??!0)&&this.start()}stop(){this.stopped=!0,this.instanceId++,this.inFlight=!1,this.currentCancel=null,this.intervalId&&(clearInterval(this.intervalId),this.intervalId=null),this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null)}start(){if(!(typeof window>"u")){if(this.stop(),this.stopped=!1,this.mode==="rest"){this.scheduleNext();return}this.intervalId=window.setInterval(()=>this.tick(),this.interval)}}isInBackground(e){this.throttle=this.keepAlive?!1:e,this.throttle&&(this.cbCount=0)}scheduleNext(){this.stopped||(this.timeoutId=window.setTimeout(()=>{this.timeoutId=null,this.tick()},this.interval))}tick(){!this.throttle||this.cbCount%10===0?this.fire():this.mode==="rest"&&this.scheduleNext(),this.throttle&&this.cbCount++}fire(){var t;this.inFlight&&this.mode==="cancel"&&((t=this.currentCancel)==null||t.call(this));const e=this.instanceId;this.cb({onStart:n=>{e===this.instanceId&&(this.inFlight=!0,this.currentCancel=n)},onFinish:()=>{e===this.instanceId&&(this.inFlight=!1,this.currentCancel=null,this.mode==="rest"&&this.scheduleNext())}})}},cD=class{constructor(){Re(this,"polls",[]);this.setupVisibilityListener()}get count(){return this.polls.length}add(e,t,n){const r=new uD(e,t,n);return this.polls.push(r),{stop:()=>r.stop(),start:()=>r.start(),destroy:()=>{r.stop(),this.polls=this.polls.filter(s=>s!==r)}}}clear(){this.polls.forEach(e=>e.stop()),this.polls=[]}setupVisibilityListener(){typeof document>"u"||document.addEventListener("visibilitychange",()=>{this.polls.forEach(e=>e.isInBackground(document.hidden))},!1)}},Z_=new cD,dD=class{constructor(){Re(this,"requestHandlers",[]);Re(this,"responseHandlers",[]);Re(this,"errorHandlers",[])}onRequest(e){return this.requestHandlers.push(e),()=>{this.requestHandlers=this.requestHandlers.filter(t=>t!==e)}}onResponse(e){return this.responseHandlers.push(e),()=>{this.responseHandlers=this.responseHandlers.filter(t=>t!==e)}}onError(e){return this.errorHandlers.push(e),()=>{this.errorHandlers=this.errorHandlers.filter(t=>t!==e)}}async processRequest(e){let t=e;for(const n of this.requestHandlers)t=await n(t);return t}async processResponse(e){let t=e;for(const n of this.responseHandlers)t=await n(t);return t}async processError(e){for(const t of this.errorHandlers)await t(e)}},Jn=new dD,p1=class extends Error{constructor(n,r,s){super(s?`${n} (${s})`:n);Re(this,"code");Re(this,"url");this.name="HttpError",this.code=r,this.url=s}},ic=class extends p1{constructor(t,n,r){super(t,"ERR_HTTP_RESPONSE",r);Re(this,"response");this.name="HttpResponseError",this.response=n}},ac=class extends p1{constructor(e="Request was cancelled",t){super(e,"ERR_CANCELLED",t),this.name="HttpCancelledError"}},e0=class extends p1{constructor(t,n,r){super(t,"ERR_NETWORK",n);Re(this,"cause");this.name="HttpNetworkError",this.cause=r}};function fD(e){const t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null}function pD(e){const t={};return e.getAllResponseHeaders().split(`\r -`).forEach(n=>{const r=n.indexOf(":");r>0&&(t[n.slice(0,r).toLowerCase().trim()]=n.slice(r+1).trim())}),t}function cC(e){return typeof FormData<"u"&&e instanceof FormData}function mD(e){return typeof e=="string"||cC(e)||typeof Blob<"u"&&e instanceof Blob||typeof ArrayBuffer<"u"&&e instanceof ArrayBuffer||typeof ArrayBuffer<"u"&&ArrayBuffer.isView(e)||typeof URLSearchParams<"u"&&e instanceof URLSearchParams}function hD(e,t){if(!t.headers)return;const n=cC(t.data);Object.entries(t.headers).forEach(([r,s])=>{(r.toLowerCase()!=="content-type"||!n)&&e.setRequestHeader(r,String(s))})}function gD(e,t){if(!t||Object.keys(t).length===0)return e;const[n]=Bc("get",e,t);return n}var dC=class{constructor(e={}){Re(this,"xsrfCookieName");Re(this,"xsrfHeaderName");this.xsrfCookieName=e.xsrfCookieName??"XSRF-TOKEN",this.xsrfHeaderName=e.xsrfHeaderName??"X-XSRF-TOKEN"}async request(e){const t=await Jn.processRequest(e);try{const n=await this.doRequest(t);return await Jn.processResponse(n)}catch(n){throw(n instanceof ic||n instanceof e0||n instanceof ac)&&await Jn.processError(n),n}}doRequest(e){return new Promise((t,n)=>{var u,c;const r=new XMLHttpRequest,s=gD(e.url,e.params);r.open(e.method.toUpperCase(),s,!0);const o=fD(this.xsrfCookieName);o&&r.setRequestHeader(this.xsrfHeaderName,o),Object.keys(e.headers??{}).some(d=>d.toLowerCase()==="x-requested-with")||r.setRequestHeader("X-Requested-With","XMLHttpRequest");let a=null;e.data!==null&&e.data!==void 0&&(mD(e.data)?a=e.data:typeof e.data=="object"?(a=JSON.stringify(e.data),!((u=e.headers)!=null&&u["Content-Type"])&&!((c=e.headers)!=null&&c["content-type"])&&r.setRequestHeader("Content-Type","application/json")):a=String(e.data)),hD(r,e),e.onUploadProgress&&(r.upload.onprogress=d=>{const f=d.lengthComputable?d.loaded/d.total:void 0;e.onUploadProgress({progress:f,percentage:f?Math.round(f*100):0,loaded:d.loaded,total:d.lengthComputable?d.total:void 0})}),e.signal&&e.signal.addEventListener("abort",()=>r.abort()),r.onabort=()=>n(new ac("Request was cancelled",e.url)),r.onerror=()=>n(new e0("Network error",e.url)),r.onload=()=>{const d={status:r.status,data:r.responseText,headers:pD(r)};r.status>=400?n(new ic(`Request failed with status ${r.status}`,d,e.url)):t(d)},r.send(a)})}},vD=new dC,Vh=vD;function yD(e){return!("request"in e)}var Dm={getClient(){return Vh},setClient(e){if(!yD(e)){Vh=e;return}Vh=new dC(e),e.xsrfCookieName&&Yn.withXsrfCookieName(e.xsrfCookieName),e.xsrfHeaderName&&Yn.withXsrfHeaderName(e.xsrfHeaderName)},onRequest:Jn.onRequest.bind(Jn),onResponse:Jn.onResponse.bind(Jn),onError:Jn.onError.bind(Jn),processRequest:Jn.processRequest.bind(Jn),processResponse:Jn.processResponse.bind(Jn),processError:Jn.processError.bind(Jn)},bD=class{constructor(){Re(this,"requestHandlers",[]);Re(this,"responseHandlers",[])}onVisitRequest(e){return this.requestHandlers.push(e),()=>{this.requestHandlers=this.requestHandlers.filter(t=>t!==e)}}onVisitResponse(e){return this.responseHandlers.push(e),()=>{this.responseHandlers=this.responseHandlers.filter(t=>t!==e)}}async processRequest(e,t){let n=t;for(const r of this.requestHandlers)n=await r(e,n);return n}async processResponse(e,t){let n=t;for(const r of this.responseHandlers)n=await r(e,n);return n}},m1=new bD;function _D(){typeof window>"u"||(window.__inertia_interceptors__=m1)}var rf=class sf{constructor(t){Re(this,"callbacks",[]);Re(this,"params");if(!t.prefetch)this.params=t;else{const n={onBefore:this.wrapCallback(t,"onBefore"),onBeforeUpdate:this.wrapCallback(t,"onBeforeUpdate"),onStart:this.wrapCallback(t,"onStart"),onProgress:this.wrapCallback(t,"onProgress"),onFinish:this.wrapCallback(t,"onFinish"),onCancel:this.wrapCallback(t,"onCancel"),onSuccess:this.wrapCallback(t,"onSuccess"),onError:this.wrapCallback(t,"onError"),onHttpException:this.wrapCallback(t,"onHttpException"),onNetworkError:this.wrapCallback(t,"onNetworkError"),onFlash:this.wrapCallback(t,"onFlash"),onCancelToken:this.wrapCallback(t,"onCancelToken"),onPrefetched:this.wrapCallback(t,"onPrefetched"),onPrefetching:this.wrapCallback(t,"onPrefetching")};this.params={...t,...n,onPrefetchResponse:t.onPrefetchResponse||(()=>{}),onPrefetchError:t.onPrefetchError||(()=>{})}}}static create(t){return new sf(t)}data(){return this.params.method==="get"?null:this.params.data}queryParams(){return this.params.method==="get"?this.params.data:{}}isPartial(){return this.params.only.length>0||this.params.except.length>0||this.params.reset.length>0}isPrefetch(){return this.params.prefetch===!0}isDeferredPropsRequest(){return this.params.deferredProps===!0}isPollRequest(){return this.params.poll===!0}onCancelToken(t){this.params.onCancelToken({cancel:t})}markAsFinished(){this.params.completed=!0,this.params.cancelled=!1,this.params.interrupted=!1}markAsCancelled({cancelled:t=!0,interrupted:n=!1}){this.params.onCancel(),this.params.completed=!1,this.params.cancelled=t,this.params.interrupted=n}wasCancelledAtAll(){return this.params.cancelled||this.params.interrupted}onFinish(){this.params.onFinish(this.params)}onStart(){this.params.onStart(this.params)}onPrefetching(){this.params.onPrefetching(this.params)}onPrefetchResponse(t){this.params.onPrefetchResponse&&this.params.onPrefetchResponse(t)}onPrefetchError(t){this.params.onPrefetchError&&this.params.onPrefetchError(t)}all(){return this.params}headers(){const t={...this.params.headers};this.isPartial()&&(t["X-Inertia-Partial-Component"]=Ve.get().component);const n=this.params.only.concat(this.params.reset);return n.length>0&&(t["X-Inertia-Partial-Data"]=n.join(",")),this.params.except.length>0&&(t["X-Inertia-Partial-Except"]=this.params.except.join(",")),this.params.reset.length>0&&(t["X-Inertia-Reset"]=this.params.reset.join(",")),this.params.errorBag&&this.params.errorBag.length>0&&(t["X-Inertia-Error-Bag"]=this.params.errorBag),t}setPreserveOptions(t){this.params.preserveScroll=sf.resolvePreserveOption(this.params.preserveScroll,t),this.params.preserveState=sf.resolvePreserveOption(this.params.preserveState,t)}runCallbacks(){this.callbacks.forEach(({name:t,args:n})=>{this.params[t](...n)})}merge(t){this.params={...this.params,...t}}wrapCallback(t,n){return(...r)=>{this.recordCallback(n,r),t[n](...r)}}recordCallback(t,n){this.callbacks.push({name:t,args:n})}static resolvePreserveOption(t,n){return typeof t=="function"?t(n):t==="errors"?Object.keys(n.props.errors||{}).length>0:t}},xD={createIframeAndPage(e){typeof e=="object"&&(e=`All Inertia requests must receive a valid Inertia response, however a plain JSON response was received.
${JSON.stringify(e)}`);const t=document.createElement("html");t.innerHTML=e,t.querySelectorAll("a").forEach(r=>r.setAttribute("target","_top"));const n=document.createElement("iframe");return n.style.backgroundColor="white",n.style.borderRadius="5px",n.style.width="100%",n.style.height="100%",n.setAttribute("sandbox","allow-scripts"),{iframe:n,page:t}},show(e){const{iframe:t,page:n}=this.createIframeAndPage(e);t.style.boxSizing="border-box",t.style.display="block";const r=document.createElement("dialog");r.id="inertia-error-dialog",Object.assign(r.style,{width:"calc(100vw - 100px)",height:"calc(100vh - 100px)",padding:"0",margin:"auto",border:"none",backgroundColor:"transparent"});const s=document.createElement("style");s.textContent=` - dialog#inertia-error-dialog::backdrop { - background-color: rgba(0, 0, 0, 0.6); - } - - dialog#inertia-error-dialog:focus { - outline: none; - } - `;const o=ei.get("nonce");o&&(s.nonce=o),document.head.appendChild(s),r.addEventListener("click",l=>{l.target===r&&r.close()}),r.addEventListener("close",()=>{s.remove(),r.remove()}),r.appendChild(t),document.body.prepend(r),r.showModal(),r.focus(),t.srcdoc=n.outerHTML}},t0=(e,t)=>e===t||e.startsWith(`${t}.`),fC=(e,t)=>{const{only:n,except:r}=e;return!(n.length===0&&r.length===0||n.length>0&&!n.some(s=>t0(t,s))||r.length>0&&r.some(s=>t0(t,s)))},kD=(e,t)=>t.some(n=>fC(e,n)),wD=new Mm,n0=class pC{constructor(t,n,r){Re(this,"requestParams");Re(this,"response");Re(this,"originatingPage");Re(this,"wasPrefetched",!1);Re(this,"processed",!1);this.requestParams=t,this.response=n,this.originatingPage=r}static create(t,n,r){return new pC(t,n,r)}isProcessed(){return this.processed}async handlePrefetch(){Kf(this.requestParams.all().url,window.location)&&this.handle()}async handle(){return wD.add(()=>this.process())}async process(){if(this.requestParams.all().prefetch)return this.wasPrefetched=!0,this.requestParams.all().prefetch=!1,this.requestParams.all().onPrefetched(this.response,this.requestParams.all()),DM(this.response,this.requestParams.all()),Promise.resolve();if(this.requestParams.runCallbacks(),this.processed=!0,!this.isInertiaResponse())return this.handleNonInertiaResponse();if(this.isHttpException()){const r={...this.response,data:this.getDataFromResponse(this.response.data)};if(this.requestParams.all().onHttpException(r)===!1||!W_(r))return}await xt.processQueue(),xt.preserveUrl=this.requestParams.all().preserveUrl,await this.setPage();const{flash:t}=Ve.get();Object.keys(t).length>0&&!this.requestParams.isDeferredPropsRequest()&&(jf(t),this.requestParams.all().onFlash(t));const n=Ve.get().props.errors||{};if(Object.keys(n).length>0){const r=this.getScopedErrors(n);return CM(r,{page:Ve.get(),visitId:this.requestParams.all().id}),this.requestParams.all().onError(r)}xe.flushByCacheTags(this.requestParams.all().invalidateCacheTags||[]),this.wasPrefetched||xe.flush(Ve.get().url),MM(Ve.get(),{visitId:this.requestParams.all().id}),await this.requestParams.all().onSuccess(Ve.get()),xt.preserveUrl=!1}mergeParams(t){this.requestParams.merge(t)}getPageResponse(){const t=this.getDataFromResponse(this.response.data);return typeof t=="object"?this.response.data={...t,flash:t.flash??{},rescuedProps:t.rescuedProps??[]}:this.response.data=t}async handleNonInertiaResponse(){if(this.isInertiaRedirect()){xe.visit(this.getHeader("x-inertia-redirect"),{...this.requestParams.all(),method:"get",data:{}});return}if(this.isLocationVisit()){const n=Lr(this.getHeader("x-inertia-location"));return X_(this.requestParams.all().url,n),this.locationVisit(n)}const t={...this.response,data:this.getDataFromResponse(this.response.data)};if(this.requestParams.all().onHttpException(t)!==!1&&W_(t))return xD.show(t.data)}isInertiaResponse(){return this.hasHeader("x-inertia")}isHttpException(){return this.response.status>=400}hasStatus(t){return this.response.status===t}getHeader(t){return this.response.headers[t]}hasHeader(t){return this.getHeader(t)!==void 0}isInertiaRedirect(){return this.hasStatus(409)&&this.hasHeader("x-inertia-redirect")}isLocationVisit(){return this.hasStatus(409)&&this.hasHeader("x-inertia-location")}locationVisit(t){try{if(typeof window>"u")return;const n=this.getHeader("x-inertia-version"),r=!!n&&n!==Ve.get().version;if(!IM(t,r)||r&&this.requestParams.all().async)return;ar.set(ar.locationVisitKey,{preserveScroll:this.requestParams.all().preserveScroll===!0}),Kf(window.location,t)?window.location.reload():window.location.href=t.href}catch{return!1}}async setPage(){const t=this.getPageResponse();return this.shouldSetPage(t)?(this.response=await m1.processResponse(this.requestParams.all(),this.response),this.mergeProps(t),Ve.mergeOncePropsIntoResponse(t),this.preserveOptimisticProps(t),this.preserveEqualProps(t),await this.setRememberedState(t),this.requestParams.setPreserveOptions(t),t.url=xt.preserveUrl?Ve.get().url:this.pageUrl(t),this.requestParams.all().onBeforeUpdate(t),OM(t),Ve.set(t,{replace:this.requestParams.all().replace,preserveScroll:this.requestParams.all().preserveScroll,preserveState:this.requestParams.all().preserveState,viewTransition:this.requestParams.all().viewTransition,cached:this.requestParams.all().cached,visitId:this.requestParams.all().id})):Promise.resolve()}getDataFromResponse(t){if(typeof t!="string")return t;try{return JSON.parse(t)}catch{return t}}shouldSetPage(t){if(!this.requestParams.all().async||this.originatingPage.component!==t.component)return!0;if(this.originatingPage.component!==Ve.get().component)return!1;const n=Lr(this.originatingPage.url),r=Lr(Ve.get().url);return n.origin===r.origin&&n.pathname===r.pathname}pageUrl(t){const n=Lr(t.url);return t.preserveFragment?n.hash=this.requestParams.all().url.hash:X_(this.requestParams.all().url,n),n.pathname+n.search+n.hash}preserveOptimisticProps(t){if(xe.hasPendingOptimistic())for(const n of Object.keys(t.props))Ve.hasBaseline(n)&&(Ve.updateBaseline(n,t.props[n]),t.props[n]=Ve.get().props[n])}preserveEqualProps(t){if(t.component!==Ve.get().component)return;const n=Ve.get().props;Object.entries(t.props).forEach(([r,s])=>{ts(s,n[r])&&(t.props[r]=n[r])})}mergeProps(t){if(!this.requestParams.isPartial()||t.component!==Ve.get().component)return;const n=t.mergeProps||[],r=t.prependProps||[],s=t.deepMergeProps||[],o=t.matchPropsOn||[],l=(c,d)=>{const f=qt(Ve.get().props,c),p=qt(t.props,c);if(Array.isArray(p)){const h=this.mergeOrMatchItems(f||[],p,c,o,d);fr(t.props,c,h)}else if(typeof p=="object"&&p!==null){const h={...f||{},...p};fr(t.props,c,h)}};n.forEach(c=>l(c,!0)),r.forEach(c=>l(c,!1)),s.forEach(c=>{const d=qt(Ve.get().props,c),f=qt(t.props,c),p=(h,b,x)=>Array.isArray(b)?this.mergeOrMatchItems(h,b,x,o):typeof b=="object"&&b!==null?Object.keys(b).reduce((w,k)=>(w[k]=p(h?h[k]:void 0,b[k],`${x}.${k}`),w),{...h}):b;fr(t.props,c,p(d,f,c))});const a=new Set([...this.requestParams.all().only,...this.requestParams.all().except].filter(c=>c.includes(".")).map(c=>c.split(".")[0]));for(const c of a){const d=Ve.get().props[c];this.isObject(d)&&this.isObject(t.props[c])&&(t.props[c]=this.deepMergeObjects(d,t.props[c]))}t.props={...Ve.get().props,...t.props},this.shouldPreserveErrors(t)&&(t.props.errors=Ve.get().props.errors),Ve.get().scrollProps&&(t.scrollProps={...Ve.get().scrollProps||{},...t.scrollProps||{}}),Ve.hasOnceProps()&&(t.onceProps={...Ve.get().onceProps||{},...t.onceProps||{}}),this.requestParams.isDeferredPropsRequest()&&(t.flash={...Ve.get().flash});const u=Ve.get().initialDeferredProps;u&&Object.keys(u).length>0&&(t.initialDeferredProps=u),t.rescuedProps=this.mergeRescuedProps(t)}mergeRescuedProps(t){const n=Ve.get().rescuedProps??[],r=t.rescuedProps??[],s=new Set(n.filter(o=>!fC(this.requestParams.all(),o)));return r.forEach(o=>s.add(o)),Array.from(s)}shouldPreserveErrors(t){if(!this.requestParams.all().preserveErrors)return!1;const n=Ve.get().props.errors;if(!n||Object.keys(n).length===0)return!1;const r=t.props.errors;return!(r&&Object.keys(r).length>0)}isObject(t){return t&&typeof t=="object"&&!Array.isArray(t)}deepMergeObjects(t,n){const r={...t};for(const s of Object.keys(n)){const o=t[s],l=n[s];this.isObject(o)&&this.isObject(l)?r[s]=this.deepMergeObjects(o,l):r[s]=l}return r}mergeOrMatchItems(t,n,r,s,o=!0){const l=Array.isArray(t)?t:[],a=s.find(d=>d.split(".").slice(0,-1).join(".")===r);if(!a)return o?[...l,...n]:[...n,...l];const u=a.split(".").pop()||"",c=new Map;return n.forEach(d=>{this.hasUniqueProperty(d,u)&&c.set(d[u],d)}),o?this.appendWithMatching(l,n,c,u):this.prependWithMatching(l,n,c,u)}appendWithMatching(t,n,r,s){const o=t.map(a=>this.hasUniqueProperty(a,s)&&r.has(a[s])?r.get(a[s]):a),l=n.filter(a=>this.hasUniqueProperty(a,s)?!t.some(u=>this.hasUniqueProperty(u,s)&&u[s]===a[s]):!0);return[...o,...l]}prependWithMatching(t,n,r,s){const o=t.filter(l=>this.hasUniqueProperty(l,s)?!r.has(l[s]):!0);return[...n,...o]}hasUniqueProperty(t,n){return t&&typeof t=="object"&&n in t}async setRememberedState(t){const n=await xt.getState(xt.rememberedState,{});this.requestParams.all().preserveState&&n&&t.component===Ve.get().component&&(t.rememberedState=n)}getScopedErrors(t){return this.requestParams.all().errorBag?t[this.requestParams.all().errorBag||""]||{}:t}},r0=class mC{constructor(t,n,{optimistic:r=!1}={}){Re(this,"page");Re(this,"response");Re(this,"cancelToken");Re(this,"requestParams");Re(this,"requestHasFinished",!1);Re(this,"optimistic");this.page=n,this.requestParams=rf.create(t),this.cancelToken=new AbortController,this.optimistic=r}static create(t,n,r){return new mC(t,n,r)}isPrefetch(){return this.requestParams.isPrefetch()}getUrl(){return this.requestParams.all().url}isOptimistic(){return this.optimistic}isPendingOptimistic(){return this.isOptimistic()&&(!this.response||!this.response.isProcessed())}async send(){this.requestParams.onCancelToken(()=>{this.response||this.cancel({cancelled:!0})}),PM(this.requestParams.all()),this.requestParams.onStart(),this.requestParams.all().prefetch&&(this.requestParams.onPrefetching(),VM(this.requestParams.all()));const t=this.requestParams.all().prefetch,n={method:this.requestParams.all().method,url:zf(this.requestParams.all().url).href,data:this.requestParams.data(),signal:this.cancelToken.signal,headers:this.getHeaders(),onUploadProgress:this.onProgress.bind(this)},r=await m1.processRequest(this.requestParams.all(),n);return Dm.getClient().request(r).then(s=>(this.response=n0.create(this.requestParams,s,this.page),this.response.handle())).catch(s=>s instanceof ic?(this.response=n0.create(this.requestParams,s.response,this.page),this.response.handle()):Promise.reject(s)).catch(s=>{if(!(s instanceof ac)&&this.requestParams.all().onNetworkError(s)!==!1&&SM(s))return t&&this.requestParams.onPrefetchError(s),Promise.reject(s)}).finally(()=>{this.finish(),t&&this.response&&this.requestParams.onPrefetchResponse(this.response)})}finish(){this.requestParams.wasCancelledAtAll()||(this.requestParams.markAsFinished(),this.fireFinishEvents())}fireFinishEvents(){this.requestHasFinished||(this.requestHasFinished=!0,EM(this.requestParams.all()),this.requestParams.onFinish())}cancel({cancelled:t=!1,interrupted:n=!1}){this.requestHasFinished||(this.cancelToken.abort(),this.requestParams.markAsCancelled({cancelled:t,interrupted:n}),this.fireFinishEvents())}onProgress(t){this.requestParams.data()instanceof FormData&&(AM(t),this.requestParams.all().onProgress(t))}getHeaders(){const t={...this.requestParams.headers(),Accept:"text/html, application/xhtml+xml","X-Requested-With":"XMLHttpRequest","X-Inertia":!0},n=Ve.get();n.version&&(t["X-Inertia-Version"]=n.version);const r=Object.entries(n.onceProps||{}).filter(([,s])=>qt(n.props,s.prop)===void 0?!1:!s.expiresAt||s.expiresAt>Date.now()).map(([s])=>s);return r.length>0&&(t["X-Inertia-Except-Once-Props"]=r.join(",")),t}},s0=class{constructor({maxConcurrent:e,interruptible:t}){Re(this,"requests",[]);Re(this,"maxConcurrent");Re(this,"interruptible");this.maxConcurrent=e,this.interruptible=t}send(e){this.requests.push(e),e.send().finally(()=>{this.requests=this.requests.filter(t=>t!==e)})}interruptInFlight(){this.cancel({interrupted:!0},!1)}cancelInFlight(e={}){const t=typeof e=="function"?e:n=>{const{prefetch:r=!0,optimistic:s=!0}=e;return(r||!n.isPrefetch())&&(s||!n.isOptimistic())};this.requests.filter(t).forEach(n=>n.cancel({cancelled:!0}))}cancel({cancelled:e=!1,interrupted:t=!1}={},n=!1){if(!n&&!this.shouldCancel())return;const r=this.requests.shift();r==null||r.cancel({cancelled:e,interrupted:t})}shouldCancel(){return this.interruptible&&this.requests.length>=this.maxConcurrent}hasPendingOptimistic(){return this.requests.some(e=>e.isPendingOptimistic())}},sr=()=>{},$D=class{constructor(){Re(this,"syncRequestStream",new s0({maxConcurrent:1,interruptible:!0}));Re(this,"asyncRequestStream",new s0({maxConcurrent:1/0,interruptible:!1}));Re(this,"clientVisitQueue",new Mm);Re(this,"pendingOptimisticCallback")}init({initialPage:e,resolveComponent:t,swapComponent:n,onFlash:r}){Ve.init({initialPage:e,resolveComponent:t,swapComponent:n,onFlash:r}),aD.handle(),ws.init(),ws.on("missingHistoryItem",()=>{typeof window<"u"&&this.visit(window.location.href,{preserveState:!0,preserveScroll:!0,replace:!0})}),ws.on("loadDeferredProps",s=>{this.loadDeferredProps(s)}),ws.on("historyQuotaExceeded",s=>{window.location.href=s})}optimistic(e){return this.pendingOptimisticCallback=e,this}get(e,t={},n={}){return this.visit(e,{...n,method:"get",data:t})}post(e,t={},n={}){return this.visit(e,{preserveState:!0,...n,method:"post",data:t})}put(e,t={},n={}){return this.visit(e,{preserveState:!0,...n,method:"put",data:t})}patch(e,t={},n={}){return this.visit(e,{preserveState:!0,...n,method:"patch",data:t})}delete(e,t={}){return this.visit(e,{preserveState:!0,...t,method:"delete"})}reload(e={}){return this.doReload(e)}doReload(e={}){if(!(typeof window>"u"))return this.visit(window.location.href,{...e,preserveScroll:!0,preserveState:!0,async:!0,headers:{...e.headers||{},"Cache-Control":"no-cache"}})}remember(e,t="default"){xt.remember(e,t)}restore(e="default"){return xt.restore(e)}on(e,t){return typeof window>"u"?()=>{}:ws.onGlobalEvent(e,t)}once(e,t){if(typeof window>"u")return()=>{};const n=this.on(e,r=>(n(),t(r)));return n}hasPendingOptimistic(){return this.asyncRequestStream.hasPendingOptimistic()}get activePolls(){return Z_.count}cancelAll({async:e=!0,prefetch:t=!0,sync:n=!0}={}){e&&this.asyncRequestStream.cancelInFlight({prefetch:t}),n&&this.syncRequestStream.cancelInFlight()}poll(e,t={},n={}){return Z_.add(e,({onStart:r,onFinish:s})=>{const o=typeof t=="function"?t():t;this.doReload({poll:!0,preserveErrors:!0,...o,onCancelToken:l=>{var a;r(l.cancel),(a=o.onCancelToken)==null||a.call(o,l)},onFinish:l=>{var a;s(),(a=o.onFinish)==null||a.call(o,l)}})},{autoStart:n.autoStart??!0,keepAlive:n.keepAlive??!1,mode:n.mode})}visit(e,t={}){t.optimistic=t.optimistic??this.pendingOptimisticCallback,this.pendingOptimisticCallback=void 0,t.optimistic&&(t.async=t.async??!0);const n=this.getPendingVisit(e,{...t,showProgress:t.showProgress??(!t.async||!!t.optimistic)}),r=this.getVisitEvents(t);if(r.onBefore(n)===!1||!K_(n))return;const s=Lr(Ve.get().url);(n.only.length>0||n.except.length>0||n.reset.length>0?mv(n.url,s):Kf(n.url,s))||this.asyncRequestStream.cancelInFlight(c=>!c.isPrefetch()&&!c.isOptimistic()&&mv(c.getUrl(),s)),n.async||this.syncRequestStream.interruptInFlight(),t.optimistic&&this.applyOptimisticUpdate(t.optimistic,r),!Ve.isCleared()&&!n.preserveUrl&&ur.save();const a={...n,...r},u=()=>{const c=hs.get(a);c?(xr.reveal(c.inFlight),hs.use(c,a)):(xr.reveal(!0),(n.async?this.asyncRequestStream:this.syncRequestStream).send(r0.create(a,Ve.get(),{optimistic:!!t.optimistic})))};Array.isArray(n.component)&&(console.error(`The "component" prop received an array of components (${n.component.join(", ")}), but only a single component string is supported for instant visits. Pass an explicit component name instead.`),n.component=null),n.component?xt.processQueue().then(()=>{this.performInstantSwap(n).then(()=>{a.preserveScroll=!0,a.preserveState=!0,a.replace=!0,a.viewTransition=!1,u()})}):u()}getCached(e,t={}){return hs.findCached(this.getPrefetchParams(e,t))}flush(e,t={}){hs.remove(this.getPrefetchParams(e,t))}flushAll(){hs.removeAll()}flushByCacheTags(e){hs.removeByTags(Array.isArray(e)?e:[e])}getPrefetching(e,t={}){return hs.findInFlight(this.getPrefetchParams(e,t))}prefetch(e,t={},n={}){if((t.method??(Qr(e)?e.method:"get"))!=="get")throw new Error("Prefetch requests must use the GET method");const s=this.getPendingVisit(e,{...t,async:!0,showProgress:!1,prefetch:!0,viewTransition:!1}),o=s.url.origin+s.url.pathname+s.url.search,l=window.location.origin+window.location.pathname+window.location.search;if(o===l)return;const a=this.getVisitEvents(t);if(a.onBefore(s)===!1||!K_(s))return;xr.hide(),this.asyncRequestStream.interruptInFlight();const u={...s,...a};new Promise(d=>{const f=()=>{Ve.get()?d():setTimeout(f,50)};f()}).then(()=>{hs.add(u,d=>{this.asyncRequestStream.send(r0.create(d,Ve.get()))},{cacheFor:ei.get("prefetch.cacheFor"),cacheTags:[],...n})})}clearHistory(){xt.clear()}decryptHistory(){return xt.decrypt()}resolveComponent(e,t){return Ve.resolve(e,t)}replace(e){this.clientVisit(e,{replace:!0})}replaceProp(e,t,n){this.replace({preserveScroll:!0,preserveState:!0,props(r){const s=typeof t=="function"?t(qt(r,e),r):t;return HM(r,e,s)},...n||{}})}appendToProp(e,t,n){this.replaceProp(e,(r,s)=>{const o=typeof t=="function"?t(r,s):t;return Array.isArray(r)||(r=r!==void 0?[r]:[]),[...r,o]},n)}prependToProp(e,t,n){this.replaceProp(e,(r,s)=>{const o=typeof t=="function"?t(r,s):t;return Array.isArray(r)||(r=r!==void 0?[r]:[]),[o,...r]},n)}push(e){this.clientVisit(e)}flash(e,t){const n=Ve.get().flash;let r;if(typeof e=="function")r=e(n);else if(typeof e=="string")r={...n,[e]:t};else if(e&&Object.keys(e).length)r={...n,...e};else return;Ve.setFlash(r),Object.keys(r).length&&jf(r)}clientVisit(e,{replace:t=!1}={}){this.clientVisitQueue.add(()=>this.performClientVisit(e,{replace:t}))}performClientVisit(e,{replace:t=!1}={}){const n=Ve.get(),r=typeof e.props=="function"?Object.fromEntries(Object.values(n.onceProps??{}).map(w=>[w.prop,qt(n.props,w.prop)])):{},s=typeof e.props=="function"?e.props(n.props,r):e.props??n.props,o=typeof e.flash=="function"?e.flash(n.flash):e.flash,{viewTransition:l,onError:a,onFinish:u,onFlash:c,onSuccess:d,...f}=e,p={...n,...f,flash:o??{},props:s},h=rf.resolvePreserveOption(e.preserveScroll??!1,p),b=rf.resolvePreserveOption(e.preserveState??!1,p),x=this.createVisitId();return Ve.set(p,{replace:t,preserveScroll:h,preserveState:b,viewTransition:l,visitId:x}).then(()=>{TM(Ve.get(),{replace:t,visitId:x});const w=Ve.get().flash;Object.keys(w).length>0&&(jf(w),c==null||c(w));const k=Ve.get().props.errors||{};if(Object.keys(k).length===0){d==null||d(Ve.get());return}const C=e.errorBag?k[e.errorBag||""]||{}:k;a==null||a(C)}).finally(()=>u==null?void 0:u(e))}performInstantSwap(e){const t=Ve.get(),n=Object.fromEntries((t.sharedProps??[]).filter(a=>a in t.props).map(a=>[a,t.props[a]])),r=typeof e.pageProps=="function"?e.pageProps(Tt(t.props),Tt(n)):e.pageProps,s=r!==null?{...r}:{...n},o=this.preserveOncePropsOnInstantVisit(t,s),l={component:e.component,url:e.url.pathname+e.url.search+e.url.hash,version:t.version,props:{...s,errors:{}},flash:{},rescuedProps:[],clearHistory:!1,encryptHistory:t.encryptHistory,sharedProps:t.sharedProps,onceProps:o,rememberedState:{}};return Ve.set(l,{replace:e.replace,preserveScroll:rf.resolvePreserveOption(e.preserveScroll,l),preserveState:!1,viewTransition:e.viewTransition,visitId:e.id})}preserveOncePropsOnInstantVisit(e,t){const n={};return Object.entries(e.onceProps??{}).forEach(([r,s])=>{if(qt(t,s.prop)!==void 0)return;const o=qt(e.props,s.prop);o!==void 0&&(fr(t,s.prop,o),n[r]=s)}),n}getPrefetchParams(e,t){return{...this.getPendingVisit(e,{...t,async:!0,showProgress:!1,prefetch:!0,viewTransition:!1}),...this.getVisitEvents(t)}}createVisitId(){return nf()}getPendingVisit(e,t){if(Qr(e)){const u=e;e=u.url,t.method=t.method??u.method}const n=ei.get("visitOptions"),r=n?n(e.toString(),Tt(t))||{}:{},s={method:"get",data:{},replace:!1,preserveScroll:!1,preserveState:!1,only:[],except:[],headers:{},errorBag:"",forceFormData:!1,queryStringArrayFormat:"brackets",async:!1,showProgress:!0,fresh:!1,reset:[],preserveUrl:!1,preserveErrors:!1,prefetch:!1,invalidateCacheTags:[],viewTransition:!1,component:null,pageProps:null,cached:!1,...G_(t),...G_(r)},[o,l]=nD(e,s.data,s.method,s.forceFormData,s.queryStringArrayFormat),a={id:this.createVisitId(),cancelled:!1,completed:!1,interrupted:!1,...s,url:o,data:l};return a.prefetch&&(a.headers.Purpose="prefetch"),a}getVisitEvents(e){return{onCancelToken:e.onCancelToken||sr,onBefore:e.onBefore||sr,onBeforeUpdate:e.onBeforeUpdate||sr,onStart:e.onStart||sr,onProgress:e.onProgress||sr,onFinish:e.onFinish||sr,onCancel:e.onCancel||sr,onSuccess:e.onSuccess||sr,onError:e.onError||sr,onHttpException:e.onHttpException||sr,onNetworkError:e.onNetworkError||sr,onFlash:e.onFlash||sr,onPrefetched:e.onPrefetched||sr,onPrefetching:e.onPrefetching||sr}}applyOptimisticUpdate(e,t){const n=Ve.get().props,r=e(Tt(n));if(!r)return;const s=[];for(const d of Object.keys(r))ts(n[d],r[d])||s.push(d);if(s.length===0)return;const o=Ve.nextOptimisticId(),l=Ve.get().component;for(const d of s)Ve.setBaseline(d,Tt(n[d]));Ve.registerOptimistic(o,e),Ve.setPropsQuietly({...n,...r});let a=!0;const u=t.onSuccess;t.onSuccess=d=>(a=!1,u(d));const c=t.onFinish;t.onFinish=d=>{if(Ve.unregisterOptimistic(o),a&&Ve.get().component===l){const f=Ve.replayOptimistics();Object.keys(f).length>0&&Ve.setPropsQuietly({...Ve.get().props,...f})}return Ve.pendingOptimisticCount()===0&&Ve.clearOptimisticState(),c(d)}}loadDeferredProps(e){e&&Object.values(e).forEach(t=>{this.doReload({only:t,deferredProps:!0,preserveErrors:!0})})}},ca=class{static createWayfinderCallback(...e){return()=>e.length===1?Qr(e[0])?e[0]:e[0]():{method:typeof e[0]=="function"?e[0]():e[0],url:typeof e[1]=="function"?e[1]():e[1]}}static parseUseFormArguments(...e){return e.length===0?{rememberKey:null,data:{},precognitionEndpoint:null}:e.length===1?{rememberKey:null,data:e[0],precognitionEndpoint:null}:e.length===2?typeof e[0]=="string"?{rememberKey:e[0],data:e[1],precognitionEndpoint:null}:{rememberKey:null,data:e[1],precognitionEndpoint:this.createWayfinderCallback(e[0])}:{rememberKey:null,data:e[2],precognitionEndpoint:this.createWayfinderCallback(e[0],e[1])}}static parseSubmitArguments(e,t){return e.length===3||e.length===2&&typeof e[0]=="string"?{method:e[0],url:e[1],options:e[2]??{}}:Qr(e[0])?{...e[0],options:e[1]??{}}:{...t(),options:e[0]??{}}}static mergeHeadersForValidation(e,t,n){const r=s=>(s.headers={...n??{},...s.headers??{}},s);return e&&typeof e=="object"&&!("target"in e)?e=r(e):t&&typeof t=="object"?t=r(t):typeof e=="string"?t=r(t??{}):e=r(e??{}),[e,t]}};function CD(e){if(!e.includes("."))return e;const t=n=>n.startsWith("[")&&n.endsWith("]")?n:n.split(".").reduce((r,s,o)=>o===0?s:`${r}[${s}]`);return e.replace(/\\\./g,"__ESCAPED_DOT__").split(/(\[[^\]]*\])/).filter(Boolean).map(t).join("").replace(/__ESCAPED_DOT__/g,".")}function SD(e){const t=[],n=/([^\[\]]+)|\[(\d*)\]/g;let r;for(;(r=n.exec(e))!==null;)r[1]!==void 0?t.push(r[1]):r[2]!==void 0&&t.push(r[2]===""?"":Number(r[2]));return t}function ED(e,t,n){let r=e;for(let s=0;s/^\d+$/.test(r)).map(Number).sort((r,s)=>r-s);return t.length===n.length&&n.length>0&&n[0]===0&&n.every((r,s)=>r===s)}function of(e){if(Array.isArray(e))return e.map(of);if(typeof e!="object"||e===null||d1(e))return e;if(OD(e)){const n=[];for(let r=0;r/^\d+$/.test(u)).map(Number).sort((u,c)=>u-c);fr(t,o,a.length>0?[...a.map(u=>l[u]),r]:[r])}else fr(t,o,[r]);continue}ED(t,s.map(String),r)}return of(t)}var Za="server";function TD(e,t){return e.match(/\sdata-inertia(=|\s|>)/)?e:e.replace(/^<([a-zA-Z][^\s/>]*)/,`<$1 data-inertia="server-head-${t}"`)}function l0(e,t){if(!t)return[];const n=typeof t=="function"?t(e):e.props[t===!0?"head":t];return Array.isArray(n)?n.map(r=>typeof r=="string"?r.trim():r).filter(r=>typeof r=="string"&&r.length>0).map(TD):[]}var AD={buildDOMElement(e){const t=document.createElement("template");t.innerHTML=e;const n=t.content.firstChild;if(!e.startsWith("