diff --git a/README.md b/README.md index e935989..ff7939e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,8 @@ The official Tasks, Projects and Time Tracking module for InvoiceShelf 3.x. It adds projects hung off a customer, tasks that move across a configurable Kanban board, time recorded by hand or by a -running timer, and a billing wizard that turns unbilled hours into invoice lines. +running timer, and invoicing that turns unbilled hours into a draft invoice from wherever the +work is: a task, a selection of tasks, a whole project, or the unbilled time page. The module is `AGPL-3.0-only`. diff --git a/app/Application/BillingService.php b/app/Application/BillingService.php index fa6938c..a3dddf2 100644 --- a/app/Application/BillingService.php +++ b/app/Application/BillingService.php @@ -101,7 +101,7 @@ public function unbilled(int $companyId, int $customerId, ?string $from = null, * Which customers have unbilled billable time, and how much of it. * * The same rule `unbilled()` applies to one customer, applied to all of - * them at once: the wizard's first step needs to know who is worth opening + * them at once: the unbilled time page needs to know who is worth opening * before it asks for anyone's entries. A customer whose work spans two * currencies gets a row per currency, because money in two denominations * cannot be added up and `prepare()` refuses such a selection anyway. @@ -163,7 +163,7 @@ public function customers(int $companyId, ?string $from = null, ?string $to = nu * Every key the host's invoice writer reads is present, including the ones * this module never sets: a line carries its zeroed discount and tax fields * so `DocumentItemService::createItems` never reaches for a missing index, - * and `notes` and `template_name` are placeholders the wizard fills in from + * and `notes` and `template_name` are placeholders the browser fills in from * the company's own defaults before it posts. * * @param 'task'|'project'|'member'|'summary' $grouping diff --git a/app/Http/Controllers/BillingController.php b/app/Http/Controllers/BillingController.php index 04dc341..f7ad1de 100644 --- a/app/Http/Controllers/BillingController.php +++ b/app/Http/Controllers/BillingController.php @@ -30,11 +30,11 @@ public function __construct(Authorizes $authorizes, private readonly BillingServ } /** - * Who has unbilled time, before the wizard asks for anyone's entries. + * Who has unbilled time, before anyone's entries are asked for. * - * One row per customer and currency, so the first step can be a list of - * people worth invoicing rather than a customer picker over the whole - * address book. + * One row per customer and currency, so the unbilled time page can open on + * a list of people worth invoicing rather than a customer picker over the + * whole address book. */ public function customers(UnbilledCustomersRequest $request): JsonResponse { diff --git a/app/Http/Requests/UnbilledCustomersRequest.php b/app/Http/Requests/UnbilledCustomersRequest.php index cb6c0f3..e4768d4 100644 --- a/app/Http/Requests/UnbilledCustomersRequest.php +++ b/app/Http/Requests/UnbilledCustomersRequest.php @@ -5,7 +5,7 @@ namespace Modules\TasksProjects\Http\Requests; /** - * The optional window the wizard's first step narrows the roll-up to. + * The optional window the unbilled time page narrows the roll-up to. * * There is no customer here on purpose: this is the list of customers, so * naming one would be asking the wrong question. diff --git a/dist/init.js b/dist/init.js index a0cc180..6af062e 100644 --- a/dist/init.js +++ b/dist/init.js @@ -61,30 +61,144 @@ var j = { en: { tasks_projects: { delete_failed: "Unable to delete the project.", customers_failed: "Unable to load the customers." } -} } }, M = { en: { tasks_projects: { billing: { - title: "Invoice time", - subtitle: "Turn unbilled hours into a draft invoice.", - invoice_time: "Invoice time", - unbilled: "Unbilled", - view_unbilled: "Invoice this time", - steps: { - customer: "Customer", - entries: "Entries", - preview: "Preview", - create: "Create" +} } }, M = v({ + busy: !1, + pending: null, + allowed: !0, + prompt: null +}); +function N() { + return !M.busy && (M.busy = !0, !0); +} +function P() { + M.busy = !1; +} +function F(e) { + M.pending = e; +} +function I() { + M.pending = null; +} +function L() { + M.allowed = !1; +} +function R(e) { + return z(null), new Promise((t) => { + M.prompt = { + suggested: e, + resolve: t + }; + }); +} +function z(e) { + let t = M.prompt; + t !== null && (M.prompt = null, t.resolve(e)); +} +function ee() { + z(null), M.busy = !1, M.pending = null, M.allowed = !0; +} +//#endregion +//#region resources/js/support/i18n.ts +function B() { + return u()?.appContext.config.globalProperties.$t ?? ((e) => e); +} +//#endregion +//#region resources/js/components/InvoiceNumberModal.vue?vue&type=script&setup=true&lang.ts +var te = { class: "flex w-full items-center justify-between" }, ne = { class: "space-y-5 px-6 py-6" }, re = { class: "text-sm text-muted" }, ie = { class: "flex justify-end space-x-3 border-t border-line-default px-6 py-4" }, ae = /* @__PURE__ */ l({ + __name: "InvoiceNumberModal", + setup(e) { + let t = B(), i = y(""), a = n(() => M.prompt !== null), l = n(() => i.value.trim() !== ""); + E(() => M.prompt, (e) => { + i.value = e?.suggested ?? ""; + }); + function u() { + l.value && z(i.value.trim()); + } + function d() { + z(null); + } + return (e, n) => { + let f = x("BaseIcon"), p = x("BaseInput"), m = x("BaseInputGroup"), h = x("BaseButton"), g = x("BaseModal"); + return _(), r(g, { + show: a.value, + onClose: d + }, { + header: D(() => [o("div", te, [o("span", null, S(C(t)("tasks_projects.billing.number.title")), 1), c(f, { + name: "XMarkIcon", + class: "h-6 w-6 cursor-pointer text-subtle hover:text-body", + onClick: d + })])]), + default: D(() => [o("form", { onSubmit: A(u, ["prevent"]) }, [o("div", ne, [o("p", re, S(C(t)("tasks_projects.billing.number.description")), 1), c(m, { + label: C(t)("tasks_projects.billing.number.label"), + required: "" + }, { + default: D(() => [c(p, { + modelValue: i.value, + "onUpdate:modelValue": n[0] ||= (e) => i.value = e, + type: "text", + name: "invoice_number", + autocomplete: "off" + }, null, 8, ["modelValue"])]), + _: 1 + }, 8, ["label"])]), o("div", ie, [c(h, { + type: "button", + variant: "primary-outline", + onClick: d + }, { + default: D(() => [s(S(C(t)("tasks_projects.general.cancel")), 1)]), + _: 1 + }), c(h, { + type: "submit", + variant: "primary", + disabled: !l.value + }, { + default: D(() => [s(S(C(t)("tasks_projects.billing.number.save")), 1)]), + _: 1 + }, 8, ["disabled"])])], 32)]), + _: 1 + }, 8, ["show"]); + }; + } +}), oe = { en: { tasks_projects: { billing: { + title: "Unbilled time", + subtitle: "Time that has not reached an invoice yet, by customer.", + back: "Back to customers", + create: "Create invoice", + busy: "Creating the invoice", + prepare_failed: "Unable to prepare the invoice.", + create_failed: "Unable to create the invoice.", + rate_failed: "Unable to read the exchange rate; the invoice was created without one.", + forbidden: "You are not allowed to invoice time.", + nothing_to_invoice: "No unbilled billable time on the selected tasks.", + mixed_customers: "Select tasks of one customer. This selection spans {count} customers.", + mixed_selection: "One invoice covers one customer in one currency. Narrow the selection.", + pending_stamp: "Finish marking the last invoice as billed before creating another one.", + created: "Invoice {number} was created.", + stamped: "{count} time entries were marked as invoiced.", + stamp_failed: "Unable to mark the time as invoiced.", + stamp_failed_notice: "Invoice {number} was created, but its time is not marked as invoiced yet.", + stamp_unmatched: "Invoice {number} was created, but its lines could not be matched back to the time behind them.", + number: { + title: "Invoice number", + description: "This company numbers its invoices by hand, so the draft needs a number before it can be created.", + label: "Number", + save: "Create invoice" + }, + retry: { + title: "The invoice was created, but the time is not marked yet", + description: "Invoice {number} exists. Its time entries still count as unbilled until they are marked, which is safe to run again.", + action: "Retry stamping", + open_invoice: "Open the invoice", + dismiss: "Forget this invoice", + dismiss_confirm: "Forget this invoice? Its time stays unbilled and can reach a second invoice." }, - back: "Back", - next: "Continue", - start_over: "Start over", customer: { - title: "Who are you invoicing?", + title: "Who has time waiting?", description: "Customers with billable time that has not reached an invoice yet.", entries: "{count} entries", empty_title: "Nothing to invoice", empty_description: "Billable time appears here once it has been logged against a task that belongs to a customer.", load_failed: "Unable to load the customers with unbilled time.", - names_failed: "Unable to load the customer names; ids are shown instead.", - unnamed: "Customer #{id}", from: "From", to: "To", clear_range: "Clear dates" @@ -114,107 +228,70 @@ var j = { en: { tasks_projects: { empty_description: "This customer has nothing waiting to be invoiced in this range.", load_failed: "Unable to load the unbilled time.", none_selected: "Select at least one entry." - }, - preview: { - title: "Check the invoice", - lines: "Invoice lines", - columns: { - description: "Description", - quantity: "Hours", - price: "Rate", - total: "Amount" - }, - sub_total: "Subtotal", - total: "Total", - invoice_date: "Invoice date", - due_date: "Due date", - invoice_number: "Invoice number", - invoice_number_auto: "Generated by the company number format.", - template: "Template", - exchange_rate: "Exchange rate", - exchange_rate_help: "1 {currency} in the company currency.", - prepare_failed: "Unable to prepare the invoice.", - templates_failed: "Unable to load the invoice templates.", - number_failed: "Unable to read the next invoice number. Type one in.", - rate_failed: "Unable to read the exchange rate. Type one in.", - create: "Create invoice", - invalid: "The invoice was refused. Fix the fields below and try again." - }, - create: { - creating: "Creating the invoice", - stamping: "Marking the time as invoiced", - created_title: "Invoice {number} created", - created_description: "{count} entries were marked as invoiced.", - view_invoice: "Open the invoice", - invoice_more: "Invoice more time", - failed: "Unable to create the invoice.", - stamp_failed_title: "The invoice was created, but the time is not marked yet", - stamp_failed_description: "Invoice {number} exists. The time entries still count as unbilled until they are stamped, which is safe to run again.", - retry_stamp: "Retry stamping", - stamped: "The time entries were marked as invoiced." } -} } } }, N = "/api/v1/tasks-projects", P = { - customers: `${N}/billing/customers`, - unbilled: `${N}/billing/unbilled`, - prepare: `${N}/billing/prepare`, - confirm: `${N}/billing/confirm` -}, F = { +} } } }, se = "/api/v1/tasks-projects", ce = { + customers: `${se}/billing/customers`, + unbilled: `${se}/billing/unbilled`, + prepare: `${se}/billing/prepare`, + confirm: `${se}/billing/confirm` +}, le = { bootstrap: "/api/v1/bootstrap", - customers: "/api/v1/customers", + customer: (e) => `/api/v1/customers/${e}`, invoices: "/api/v1/invoices", invoiceTemplates: "/api/v1/invoices/templates", nextNumber: "/api/v1/next-number", exchangeRate: (e) => `/api/v1/currencies/${e}/exchange-rate` }; -async function I(e, t = {}) { - let { data: n } = await e.get(P.customers, { params: t }); +async function ue(e, t = {}) { + let { data: n } = await e.get(ce.customers, { params: t }); return n.data ?? []; } -async function L(e, t, n = {}) { - let { data: r } = await e.get(P.unbilled, { params: { +async function de(e, t, n = {}) { + let { data: r } = await e.get(ce.unbilled, { params: { customer_id: t, ...n } }); return r.data; } -async function ee(e, t, n) { - let { data: r } = await e.post(P.prepare, { - entry_ids: t, - grouping: n - }); - return r.data; +async function fe(e, t) { + let { data: n } = await e.post(ce.prepare, pe(t)); + return n.data; +} +function pe(e) { + let t = "taskIds" in e ? { task_ids: e.taskIds } : "projectId" in e ? { project_id: e.projectId } : { entry_ids: e.entryIds }; + return e.grouping !== void 0 && (t.grouping = e.grouping), t; } -async function R(e, t, n) { - let { data: r } = await e.post(P.confirm, { +async function me(e, t, n) { + let { data: r } = await e.post(ce.confirm, { invoice_id: t, items: n }); return r?.stamped ?? 0; } -async function te(e, t = 200) { - let { data: n } = await e.get(F.customers, { params: { limit: t } }); - return n.data ?? []; +async function he(e, t) { + let { data: n } = await e.get(le.customer(t)); + return n?.data ?? null; } -async function ne(e, t) { - let { data: n } = await e.post(F.invoices, t); +async function ge(e, t) { + let { data: n } = await e.post(le.invoices, t); return n.data; } -async function re(e) { - let { data: t } = await e.get(F.invoiceTemplates); +async function _e(e) { + let { data: t } = await e.get(le.invoiceTemplates); return t?.invoiceTemplates ?? []; } -async function ie(e, t) { +async function ve(e, t) { let n = { key: "invoice" }; t !== void 0 && (n.userId = t); - let { data: r } = await e.get(F.nextNumber, { params: n }); + let { data: r } = await e.get(le.nextNumber, { params: n }); return r?.success && typeof r.nextNumber == "string" ? r.nextNumber : null; } -async function ae(e, t) { - let { data: n } = await e.get(F.exchangeRate(t)), r = Array.isArray(n?.exchangeRate) ? n.exchangeRate[0] : n?.exchangeRate, i = Number(r); +async function ye(e, t) { + let { data: n } = await e.get(le.exchangeRate(t)), r = Array.isArray(n?.exchangeRate) ? n.exchangeRate[0] : n?.exchangeRate, i = Number(r); return Number.isFinite(i) && i > 0 ? i : null; } -async function oe(e) { - let { data: t } = await e.get(F.bootstrap), n = t?.current_company_settings ?? {}, r = t?.current_user_settings ?? {}, i = Number(n.invoice_due_date_days), a = r.default_invoice_template; +async function be(e) { + let { data: t } = await e.get(le.bootstrap), n = t?.current_company_settings ?? {}, r = t?.current_user_settings ?? {}, i = Number(n.invoice_due_date_days), a = r.default_invoice_template; return { currency: t?.current_company_currency ?? null, dueDateDays: Number.isFinite(i) && i >= 0 ? i : 0, @@ -224,59 +301,186 @@ async function oe(e) { }; } //#endregion +//#region resources/js/api/time.ts +var xe = "/api/v1/tasks-projects", Se = { + timeEntries: `${xe}/time-entries`, + timeEntry: (e) => `${xe}/time-entries/${e}`, + timer: `${xe}/timer`, + timerStart: `${xe}/timer/start`, + timerStop: `${xe}/timer/stop`, + taskStatuses: `${xe}/task-statuses`, + taskStatus: (e) => `${xe}/task-statuses/${e}`, + reorderTaskStatuses: `${xe}/task-statuses/reorder`, + tasks: `${xe}/tasks`, + task: (e) => `${xe}/tasks/${e}`, + members: `${xe}/members`, + settings: `${xe}/settings` +}, Ce = { bootstrap: "/api/v1/bootstrap" }, we = 100, Te = 5, Ee = 10; +async function De(e, t) { + let { data: n } = await e.get(Se.timeEntries, { params: t }); + return n; +} +async function Oe(e, t) { + let n = []; + for (let r = 1; r <= Te; r += 1) { + let i = await De(e, { + ...t, + page: r, + limit: we + }); + if (n.push(...i.data ?? []), !i.meta || r >= i.meta.last_page) break; + } + return n; +} +async function ke(e, t) { + let { data: n } = await e.post(Se.timeEntries, t); + return n.data; +} +async function Ae(e, t, n) { + let { data: r } = await e.put(Se.timeEntry(t), n); + return r.data; +} +async function je(e, t) { + await e.delete(Se.timeEntry(t)); +} +async function Me(e) { + let { data: t } = await e.get(Se.timer); + return t?.data ?? null; +} +async function Ne(e, t) { + let { data: n } = await e.post(Se.timerStart, t); + return n.data; +} +async function Pe(e) { + let { data: t } = await e.post(Se.timerStop); + return t.data; +} +async function Fe(e) { + await e.delete(Se.timer); +} +async function Ie(e) { + let { data: t } = await e.get(Se.taskStatuses); + return t.data ?? []; +} +async function Le(e, t) { + let { data: n } = await e.post(Se.taskStatuses, t); + return n.data; +} +async function Re(e, t, n) { + let { data: r } = await e.put(Se.taskStatus(t), n); + return r.data; +} +async function ze(e, t) { + await e.delete(Se.taskStatus(t)); +} +async function Be(e, t) { + let { data: n } = await e.post(Se.reorderTaskStatuses, { ids: t }); + return n.data ?? []; +} +async function Ve(e, t, n = Ee) { + let r = { limit: n }; + t.trim() !== "" && (r.search = t.trim()); + let { data: i } = await e.get(Se.tasks, { params: r }); + return i.data ?? []; +} +async function He(e, t) { + let { data: n } = await e.get(Se.task(t)); + return n.data; +} +async function Ue(e) { + let { data: t } = await e.get(Se.settings); + return t.data; +} +async function We(e) { + let { data: t } = await e.get(Ce.bootstrap), n = t?.current_user?.id; + return typeof n == "number" ? n : null; +} +//#endregion +//#region resources/js/stores/tasks.ts +var Ge = v({}), Ke = /* @__PURE__ */ new Set(), qe = 5, Je = { + logged_minutes: 0, + billable_minutes: 0, + unbilled_minutes: 0, + unbilled_amount: 0, + invoiced: "none", + running: [] +}, Ye = y(0), Xe = v({}); +function Ze(e) { + return e === null ? "" : Ge[e] ?? `#${e}`; +} +function Qe(e) { + e && typeof e.id == "number" && typeof e.name == "string" && (Ge[e.id] = e.name); +} +async function $e(e, t) { + let n = [...new Set(t)].filter((e) => typeof e == "number" && Ge[e] === void 0 && !Ke.has(e)); + for (let e of n) Ke.add(e); + for (let t = 0; t < n.length; t += qe) await Promise.all(n.slice(t, t + qe).map(async (t) => { + try { + Qe(await He(e, t)); + } catch {} finally { + Ke.delete(t); + } + })); +} +var et = Ye; +function V() { + Ye.value += 1; +} +function tt(e, t) { + Xe[e] = { + ...Xe[e] ?? {}, + ...t + }; +} +function nt(e) { + if (!e || typeof e.id != "number") return Je; + let t = e.time ?? Je; + return { + ...Je, + ...t, + running: Array.isArray(t.running) ? t.running : [], + ...Xe[e.id] ?? {} + }; +} +function rt() { + for (let e of Object.keys(Ge)) delete Ge[Number(e)]; + for (let e of Object.keys(Xe)) delete Xe[Number(e)]; + Ke.clear(); +} +//#endregion //#region resources/js/support/errors.ts -function se(e) { +function it(e) { if (typeof e != "object" || !e) return null; let t = e.response; return typeof t?.data != "object" || t.data === null ? null : t.data; } -function z(e, t) { - let n = se(e)?.message; +function H(e, t) { + let n = it(e)?.message; return typeof n == "string" && n !== "" ? n : t; } -function ce(e) { - let t = se(e)?.errors, n = {}; +function at(e) { + let t = it(e)?.errors, n = {}; if (typeof t != "object" || !t) return n; for (let [e, r] of Object.entries(t)) Array.isArray(r) && typeof r[0] == "string" && (n[e] = r[0]); return n; } //#endregion -//#region resources/js/support/http.ts -function le(e) { - if (typeof e != "object" || !e) return null; - let t = e.response?.status; - return typeof t == "number" ? t : null; -} -function B(e) { - if (typeof e != "object" || !e) return null; - let t = e.response?.data; - if (typeof t != "object" || !t) return null; - let n = t.error; - return typeof n == "string" && n !== "" ? n : null; -} -function ue(e) { - return le(e) === 409; -} -function de(e) { - return le(e) === 403; -} -//#endregion //#region resources/js/support/format.ts -function fe(e) { +function ot(e) { return e === null ? "" : String(e / 100); } -function pe(e) { +function st(e) { let t = Number(e); return e.trim() === "" || Number.isNaN(t) ? null : Math.round(t * 100); } -function me(e) { +function ct(e) { return e === null ? "" : String(e / 60); } -function he(e) { +function lt(e) { let t = Number(e); return e.trim() === "" || Number.isNaN(t) ? null : Math.round(t * 60); } -function ge(e) { +function ut(e) { if (!e) return ""; let [t, n, r] = e.slice(0, 10).split("-").map(Number); return !t || !n || !r ? e : new Date(Date.UTC(t, n - 1, r)).toLocaleDateString(void 0, { @@ -286,51 +490,346 @@ function ge(e) { timeZone: "UTC" }); } -function _e(e) { +function dt(e) { if (typeof e == "string") return e.slice(0, 10); let t = String(e.getMonth() + 1).padStart(2, "0"), n = String(e.getDate()).padStart(2, "0"); return `${e.getFullYear()}-${t}-${n}`; } -function ve(e) { +function ft(e) { let t = Math.max(0, Math.round(e ?? 0)), n = Math.floor(t / 60), r = t % 60; return n === 0 ? `${r}m` : r === 0 ? `${n}h` : `${n}h ${r}m`; } -function ye(e) { +function pt(e) { let t = e.trim().split(/\s+/).filter(Boolean); return t.length === 0 ? "?" : (t[0].charAt(0) + (t.length > 1 ? t[t.length - 1].charAt(0) : "")).toUpperCase(); } -function be(e) { +function mt(e) { if (!e) return !1; let t = /* @__PURE__ */ new Date(), n = `${t.getFullYear()}-${String(t.getMonth() + 1).padStart(2, "0")}-${String(t.getDate()).padStart(2, "0")}`; return e.slice(0, 10) < n; } //#endregion -//#region resources/js/support/i18n.ts -function V() { - return u()?.appContext.config.globalProperties.$t ?? ((e) => e); +//#region resources/js/support/http.ts +function ht(e) { + if (typeof e != "object" || !e) return null; + let t = e.response?.status; + return typeof t == "number" ? t : null; +} +function gt(e) { + if (typeof e != "object" || !e) return null; + let t = e.response?.data; + if (typeof t != "object" || !t) return null; + let n = t.error; + return typeof n == "string" && n !== "" ? n : null; +} +function _t(e) { + return ht(e) === 409; +} +function vt(e) { + return ht(e) === 403; +} +//#endregion +//#region resources/js/support/invoicing.ts +var yt = "/admin/invoices"; +async function bt(e, t) { + let { notify: n, t: r } = e; + if (M.pending !== null) return n("warning", r("tasks_projects.billing.pending_stamp")), !1; + if (!N()) return !1; + try { + return await Ct(e, t); + } finally { + P(); + } +} +async function xt(e, t, n) { + let r = M.pending; + if (r === null || !N()) return !1; + try { + let i = await me(e, r.invoiceId, r.items); + return I(), V(), t("success", n("tasks_projects.billing.stamped", { count: i })), !0; + } catch (e) { + return t("error", H(e, n("tasks_projects.billing.stamp_failed"))), !1; + } finally { + P(); + } +} +function St(e) { + return `${yt}/${e}/view`; +} +async function Ct(e, t) { + let { client: n, notify: r, t: i } = e, a; + try { + a = await fe(n, t); + } catch (t) { + return wt(e, t), !1; + } + if (!Array.isArray(a.items) || a.items.length === 0) return r("warning", i("tasks_projects.billing.nothing_to_invoice")), !1; + let [o, s, c] = await Promise.all([ + be(n).catch(() => null), + _e(n).catch(() => []), + he(n, a.customer_id).catch(() => null) + ]), l = c?.currency_id ?? c?.currency?.id ?? a.currency_id, u = o?.currency?.id ?? null, d = u !== null && l !== null && l !== u, f = await Et(e, o, a.customer_id); + if (f === null) return !1; + let p = null; + d && l !== null && (p = await ye(n, l).catch(() => null), p === null && r("warning", i("tasks_projects.billing.rate_failed"))); + let m = Ot(a, { + invoiceNumber: f, + currencyId: l, + exchangeRate: p, + dueDate: Dt(a.invoice_date, o), + templateName: o?.defaultTemplate ?? s[0]?.name ?? "" + }), h; + try { + h = await ge(n, m); + } catch (e) { + return r("error", H(e, i("tasks_projects.billing.create_failed"))), !1; + } + let g = await kt(e, h, a); + return V(), g ? (r("success", i("tasks_projects.billing.created", { number: h.invoice_number })), await jt(e.router, h.id), !0) : !1; +} +function wt(e, t) { + let { notify: n, t: r } = e, i = gt(t); + if (i === "mixed_billing_selection") { + let e = Tt(t); + n("error", e > 1 ? r("tasks_projects.billing.mixed_customers", { count: e }) : H(t, r("tasks_projects.billing.mixed_selection"))); + return; + } + if (i === "nothing_to_invoice") { + n("warning", r("tasks_projects.billing.nothing_to_invoice")); + return; + } + if (ht(t) === 403) { + L(), n("error", r("tasks_projects.billing.forbidden")); + return; + } + n("error", H(t, r("tasks_projects.billing.prepare_failed"))); +} +function Tt(e) { + if (typeof e != "object" || !e) return 0; + let t = e.response?.data; + if (typeof t != "object" || !t) return 0; + let n = t.customer_ids; + return Array.isArray(n) ? n.length : 0; +} +async function Et(e, t, n) { + let r = await ve(e.client, n).catch(() => null); + return t?.autoGenerateNumber !== !1 && r !== null ? r : R(r ?? ""); +} +function Dt(e, t) { + if (t === null || !t.setDueDateAutomatically) return null; + let n = /* @__PURE__ */ new Date(`${e}T00:00:00`); + return Number.isNaN(n.getTime()) ? null : (n.setDate(n.getDate() + t.dueDateDays), dt(n)); +} +function Ot(e, t) { + return { + invoice_date: e.invoice_date, + due_date: t.dueDate, + customer_id: e.customer_id, + invoice_number: t.invoiceNumber, + currency_id: t.currencyId, + exchange_rate: t.exchangeRate, + discount: e.discount, + discount_type: e.discount_type, + discount_val: e.discount_val, + tax: e.tax, + sub_total: e.sub_total, + total: e.total, + tax_included: !1, + notes: e.notes, + template_name: t.templateName, + items: e.items.map((e) => ({ ...e })), + taxes: [] + }; +} +async function kt(e, t, n) { + let { client: r, notify: i, t: a } = e, o = At(t, n); + if (o.length === 0) return i("error", a("tasks_projects.billing.stamp_unmatched", { number: t.invoice_number })), await jt(e.router, t.id), !1; + try { + return await me(r, t.id, o), !0; + } catch (e) { + return F({ + invoiceId: t.id, + invoiceNumber: t.invoice_number, + items: o + }), i("error", H(e, a("tasks_projects.billing.stamp_failed_notice", { number: t.invoice_number }))), !1; + } +} +function At(e, t) { + let n = Array.isArray(e.items) ? e.items : [], r = Array.isArray(t.groups) ? t.groups : [], i = []; + return r.forEach((e, t) => { + let r = n[t]; + r && typeof r.id == "number" && e.entry_ids.length > 0 && i.push({ + invoice_item_id: r.id, + entry_ids: e.entry_ids + }); + }), i; +} +async function jt(e, t) { + await Mt(e, `${yt}/${t}/edit`) || await Mt(e, St(t)); +} +async function Mt(e, t) { + try { + return !await e.push(t); + } catch { + return !1; + } +} +//#endregion +//#region resources/js/components/InvoiceRetryBanner.vue?vue&type=script&setup=true&lang.ts +var Nt = { + key: 0, + class: "mt-4 rounded-xl border border-status-yellow bg-surface p-5", + role: "alert" +}, Pt = { class: "text-sm font-semibold text-heading" }, Ft = { class: "mt-1 text-sm text-muted" }, It = { class: "mt-4 flex flex-wrap items-center gap-3" }, Lt = /* @__PURE__ */ l({ + __name: "InvoiceRetryBanner", + props: { + client: { type: [Function, Object] }, + notify: { type: Function } + }, + setup(e) { + let t = e, r = B(), l = y(!1), u = n(() => M.pending); + async function d() { + if (!l.value) { + l.value = !0; + try { + await xt(t.client, t.notify, r); + } finally { + l.value = !1; + } + } + } + function f() { + window.confirm(r("tasks_projects.billing.retry.dismiss_confirm")) && I(); + } + return (e, t) => { + let n = x("BaseButton"), p = x("router-link"); + return u.value ? (_(), a("div", Nt, [ + o("p", Pt, S(C(r)("tasks_projects.billing.retry.title")), 1), + o("p", Ft, S(C(r)("tasks_projects.billing.retry.description", { number: u.value.invoiceNumber })), 1), + o("div", It, [ + c(n, { + variant: "primary", + loading: l.value, + disabled: l.value, + onClick: d + }, { + default: D(() => [s(S(C(r)("tasks_projects.billing.retry.action")), 1)]), + _: 1 + }, 8, ["loading", "disabled"]), + c(p, { to: C(St)(u.value.invoiceId) }, { + default: D(() => [c(n, { variant: "white" }, { + default: D(() => [s(S(C(r)("tasks_projects.billing.retry.open_invoice")), 1)]), + _: 1 + })]), + _: 1 + }, 8, ["to"]), + o("button", { + type: "button", + class: "text-sm font-medium text-muted hover:underline", + onClick: f + }, S(C(r)("tasks_projects.billing.retry.dismiss")), 1) + ]) + ])) : i("", !0); + }; + } +}), Rt = "/api/v1/tasks-projects", zt = { + projects: `${Rt}/projects`, + project: (e) => `${Rt}/projects/${e}`, + archiveProject: (e) => `${Rt}/projects/${e}/archive`, + unarchiveProject: (e) => `${Rt}/projects/${e}/unarchive`, + members: `${Rt}/members`, + settings: `${Rt}/settings` +}, Bt = { customers: "/api/v1/customers" }; +function Vt(e, t) { + if (e === void 0 || e.order === "") return {}; + let n = t[e.fieldName]; + return n === void 0 ? {} : { + sort_by: n, + sort_order: e.order + }; +} +async function Ht(e, t) { + let { data: n } = await e.get(zt.projects, { params: t }); + return n; +} +async function Ut(e, t) { + let { data: n } = await e.post(zt.projects, t); + return n.data; +} +async function Wt(e, t, n) { + let { data: r } = await e.put(zt.project(t), n); + return r.data; +} +async function Gt(e, t) { + let { data: n } = await e.post(zt.archiveProject(t)); + return n.data; +} +async function Kt(e, t) { + let { data: n } = await e.post(zt.unarchiveProject(t)); + return n.data; +} +async function qt(e, t) { + await e.delete(zt.project(t)); +} +async function Jt(e) { + let { data: t } = await e.get(zt.members); + return t.data; +} +async function Yt(e, t = 100) { + let { data: n } = await e.get(Bt.customers, { params: { limit: t } }); + return n.data; +} +var Xt = v({}), Zt = !1, Qt = null; +function $t(e) { + return e === null ? "" : Xt[e] ?? `#${e}`; +} +async function en(e) { + Zt || (Qt ??= nn(e), await Qt); +} +function tn() { + for (let e of Object.keys(Xt)) delete Xt[Number(e)]; + Zt = !1, Qt = null; +} +async function nn(e) { + try { + for (let t of await Yt(e, 200)) { + let e = t?.id; + typeof e == "number" && (Xt[e] = rn(t)); + } + Zt = !0; + } catch {} finally { + Qt = null; + } +} +function rn(e) { + let t = typeof e.display_name == "string" ? e.display_name.trim() : ""; + if (t !== "") return t; + let n = typeof e.name == "string" ? e.name.trim() : ""; + return n === "" ? `#${e.id}` : n; } //#endregion //#region resources/js/support/page.ts -var H = "tasks-projects", xe = `/admin/modules/${H}`, Se = { - tasks: xe, - board: `${xe}/board`, - week: `${xe}/week`, - task: (e) => `${xe}/tasks/${e}`, - projects: `${xe}/projects`, - project: (e) => `${xe}/projects/${e}`, - reports: `${xe}/reports`, +var U = "tasks-projects", an = `/admin/modules/${U}`, W = { + tasks: an, + board: `${an}/board`, + week: `${an}/week`, + task: (e) => `${an}/tasks/${e}`, + projects: `${an}/projects`, + project: (e) => `${an}/projects/${e}`, + reports: `${an}/reports`, + billing: `${an}/billing`, settings: "/admin/settings/modules", customer: (e) => `/admin/customers/${e}/view` -}, Ce = { - tasks: `extension.page.${H}.tasks`, - list: `extension.page.${H}.tasks.list`, - board: `extension.page.${H}.tasks.board`, - week: `extension.page.${H}.tasks.week`, - task: `extension.page.${H}.task`, - projects: `extension.page.${H}.projects`, - project: `extension.page.${H}.project` +}, on = { + tasks: `extension.page.${U}.tasks`, + list: `extension.page.${U}.tasks.list`, + board: `extension.page.${U}.tasks.board`, + week: `extension.page.${U}.tasks.week`, + task: `extension.page.${U}.task`, + projects: `extension.page.${U}.projects`, + project: `extension.page.${U}.project` }; -function we(e, t) { +function sn(e, t) { return l({ setup: (n, { attrs: r }) => () => d(t, { ...r, client: e.client, @@ -341,60 +840,24 @@ function we(e, t) { }) }); } //#endregion -//#region resources/js/pages/BillingPage.vue?vue&type=script&setup=true&lang.ts -var Te = { class: "flex items-center justify-end space-x-5" }, Ee = { class: "mt-6 flex flex-wrap items-center gap-x-6 gap-y-3" }, De = { +//#region resources/js/pages/UnbilledTimePage.vue?vue&type=script&setup=true&lang.ts +var cn = { class: "mt-2 text-sm text-muted" }, ln = { class: "flex flex-wrap items-center justify-end gap-3" }, un = { class: "mt-4 flex flex-wrap items-end gap-4" }, dn = { key: 0, class: "flex justify-center py-16" -}, Oe = { +}, fn = { key: 1, class: "mt-6" -}, ke = { class: "text-base font-semibold text-heading" }, Ae = { class: "mt-1 text-sm text-muted" }, je = { class: "mt-4 flex flex-wrap items-end gap-4" }, Me = { +}, pn = { class: "text-base font-semibold text-heading" }, mn = { class: "mt-1 text-sm text-muted" }, hn = { key: 0, class: "mt-5 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3" -}, Ne = ["onClick"], Pe = { class: "text-sm font-semibold text-heading" }, Fe = { class: "mt-1 text-xs text-muted" }, Ie = { class: "mt-3 text-xl font-semibold text-heading" }, Le = { +}, gn = ["onClick"], _n = { class: "text-sm font-semibold text-heading" }, vn = { class: "mt-1 text-xs text-muted" }, yn = { class: "mt-3 text-xl font-semibold text-heading" }, bn = { key: 2, class: "mt-6" -}, Re = { class: "flex flex-wrap items-end justify-between gap-4" }, ze = { class: "text-base font-semibold text-heading" }, Be = { class: "mt-1 text-sm text-muted" }, Ve = { +}, xn = { class: "flex flex-wrap items-end justify-between gap-4" }, Sn = { class: "text-base font-semibold text-heading" }, Cn = { class: "mt-1 text-sm text-muted" }, wn = { key: 0, class: "flex justify-center py-16" -}, He = { class: "mt-4 flex flex-wrap items-center justify-between gap-3 rounded-lg border border-line-default bg-surface-secondary px-4 py-3" }, Ue = { class: "flex cursor-pointer items-center gap-2 text-sm font-medium text-heading" }, We = ["checked"], Ge = { class: "text-sm text-muted" }, Ke = { class: "flex flex-wrap items-center justify-between gap-3 bg-surface-secondary px-4 py-3" }, qe = { class: "flex cursor-pointer items-center gap-2 text-sm font-semibold text-heading" }, Je = ["checked", "onChange"], Ye = { class: "text-sm text-muted" }, Xe = { class: "overflow-x-auto" }, Ze = { class: "w-full table-auto" }, Qe = { class: "bg-surface text-xs tracking-wider text-muted uppercase" }, $e = { class: "px-4 py-2 text-left font-medium" }, et = { class: "px-4 py-2 text-left font-medium" }, tt = { class: "px-4 py-2 text-left font-medium" }, nt = { class: "px-4 py-2 text-left font-medium" }, rt = { class: "px-4 py-2 text-right font-medium" }, it = { class: "px-4 py-2 text-right font-medium" }, at = { class: "divide-y divide-line-default bg-surface text-sm" }, ot = { class: "pl-4" }, st = ["checked", "onChange"], ct = { class: "px-4 py-2 whitespace-nowrap text-muted" }, lt = { class: "px-4 py-2" }, ut = { class: "text-heading" }, dt = { class: "block text-xs text-subtle" }, ft = { class: "px-4 py-2 text-muted" }, pt = { class: "px-4 py-2 text-muted" }, mt = { class: "px-4 py-2 text-right whitespace-nowrap text-muted" }, ht = { class: "px-4 py-2 text-right whitespace-nowrap text-heading" }, gt = { class: "mt-5 flex flex-wrap items-center justify-between gap-4" }, _t = { class: "text-sm font-medium text-heading" }, vt = { class: "flex items-center gap-3" }, yt = { - key: 3, - class: "mt-6" -}, bt = { class: "text-base font-semibold text-heading" }, xt = { - key: 0, - class: "flex justify-center py-16" -}, St = { - key: 0, - class: "mt-4 rounded-lg border border-status-red bg-surface px-4 py-3 text-sm text-status-red" -}, Ct = { class: "mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4" }, wt = { - key: 0, - class: "mt-1 block text-xs text-subtle" -}, Tt = { class: "mt-1 block text-xs text-subtle" }, Et = { class: "mt-5 overflow-hidden rounded-xl border border-line-default" }, Dt = { class: "overflow-x-auto" }, Ot = { class: "w-full table-auto" }, kt = { class: "bg-surface-secondary text-xs tracking-wider text-muted uppercase" }, At = { class: "px-4 py-2 text-left font-medium" }, jt = { class: "px-4 py-2 text-right font-medium" }, Mt = { class: "px-4 py-2 text-right font-medium" }, Nt = { class: "px-4 py-2 text-right font-medium" }, Pt = { class: "divide-y divide-line-default bg-surface text-sm" }, Ft = { class: "px-4 py-3" }, It = { class: "font-medium text-heading" }, Lt = { - key: 0, - class: "mt-1 block text-xs whitespace-pre-line text-subtle" -}, Rt = { class: "px-4 py-3 text-right whitespace-nowrap text-muted" }, zt = { class: "px-4 py-3 text-right whitespace-nowrap text-muted" }, Bt = { class: "px-4 py-3 text-right whitespace-nowrap font-medium text-heading" }, Vt = { class: "bg-surface-secondary text-sm" }, Ht = { - class: "px-4 py-2 text-right text-muted", - colspan: "3" -}, Ut = { class: "px-4 py-2 text-right whitespace-nowrap text-heading" }, Wt = { - class: "px-4 py-2 text-right font-semibold text-heading", - colspan: "3" -}, Gt = { class: "px-4 py-2 text-right whitespace-nowrap font-semibold text-heading" }, Kt = { class: "mt-5 flex items-center justify-end gap-3" }, qt = { - key: 4, - class: "mt-6" -}, Jt = { - key: 0, - class: "flex flex-col items-center gap-3 py-16" -}, Yt = { class: "text-sm text-muted" }, Xt = { - key: 0, - class: "rounded-xl border border-status-yellow bg-surface p-5" -}, Zt = { class: "text-sm font-semibold text-heading" }, Qt = { class: "mt-1 text-sm text-muted" }, $t = { class: "mt-4 flex flex-wrap items-center gap-3" }, en = { - key: 1, - class: "rounded-xl border border-line-default bg-surface p-6 text-center" -}, tn = { class: "mt-3 text-base font-semibold text-heading" }, nn = { class: "mt-1 text-sm text-muted" }, rn = { class: "mt-3 text-2xl font-semibold text-heading" }, an = { class: "mt-5 flex flex-wrap items-center justify-center gap-3" }, on = { - key: 2, - class: "flex justify-center py-16" -}, sn = "/admin/invoices", cn = /* @__PURE__ */ l({ - __name: "BillingPage", +}, Tn = { class: "mt-4 flex flex-wrap items-center justify-between gap-3 rounded-lg border border-line-default bg-surface-secondary px-4 py-3" }, En = { class: "flex cursor-pointer items-center gap-2 text-sm font-medium text-heading" }, Dn = ["checked"], On = { class: "text-sm text-muted" }, kn = { class: "flex flex-wrap items-center justify-between gap-3 bg-surface-secondary px-4 py-3" }, An = { class: "flex cursor-pointer items-center gap-2 text-sm font-semibold text-heading" }, jn = ["checked", "onChange"], Mn = { class: "text-sm text-muted" }, Nn = { class: "overflow-x-auto" }, Pn = { class: "w-full table-auto" }, Fn = { class: "bg-surface text-xs tracking-wider text-muted uppercase" }, In = { class: "px-4 py-2 text-left font-medium" }, Ln = { class: "px-4 py-2 text-left font-medium" }, Rn = { class: "px-4 py-2 text-left font-medium" }, zn = { class: "px-4 py-2 text-left font-medium" }, Bn = { class: "px-4 py-2 text-right font-medium" }, Vn = { class: "px-4 py-2 text-right font-medium" }, Hn = { class: "divide-y divide-line-default bg-surface text-sm" }, Un = { class: "pl-4" }, Wn = ["checked", "onChange"], Gn = { class: "px-4 py-2 whitespace-nowrap text-muted" }, Kn = { class: "px-4 py-2" }, qn = { class: "block text-xs text-subtle" }, Jn = { class: "px-4 py-2 text-muted" }, Yn = { class: "px-4 py-2 text-muted" }, Xn = { class: "px-4 py-2 text-right whitespace-nowrap text-muted" }, Zn = { class: "px-4 py-2 text-right whitespace-nowrap text-heading" }, Qn = { class: "mt-5 flex flex-wrap items-center justify-between gap-4" }, $n = { class: "text-sm font-medium text-heading" }, er = { class: "flex items-center gap-3" }, tr = /* @__PURE__ */ l({ + __name: "UnbilledTimePage", props: { client: { type: [Function, Object] }, notify: { type: Function }, @@ -406,616 +869,329 @@ var Te = { class: "flex items-center justify-end space-x-5" }, Ee = { class: "mt "project", "member", "summary" - ], d = V(), p = y(1), m = y(!0), g = y([]), w = y({}), T = v({ + ], d = B(), p = y(!0), m = y([]), g = v({ from: "", to: "" - }), O = y(null), k = y(null), A = y("task"), j = y([]), M = y(!1), N = y(null), P = y([]), F = y(null), se = y(!1), B = v({ - invoiceDate: "", - dueDate: "", - invoiceNumber: "", - templateName: "", - exchangeRate: "" - }), ue = y({}), de = y(!1), fe = y(!1), pe = y(null), me = y(null), he = y(!1), ye = y(!1), be = n(() => [ - d("tasks_projects.billing.steps.customer"), - d("tasks_projects.billing.steps.entries"), - d("tasks_projects.billing.steps.preview"), - d("tasks_projects.billing.steps.create") - ]), H = n(() => u.map((e) => ({ + }), w = y(null), T = y(null), O = y(!1), k = y("task"), A = y([]), j = n(() => M.busy), N = n(() => u.map((e) => ({ id: e, label: d(`tasks_projects.billing.entries.group_by.${e}`) - }))), xe = n({ - get: () => H.value.find((e) => e.id === A.value) ?? H.value[0], + }))), P = n({ + get: () => N.value.find((e) => e.id === k.value) ?? N.value[0], set: (e) => { - A.value = e.id; + k.value = e.id; } - }), Ce = n(() => P.value.map((e) => ({ name: e.name }))), we = n({ - get: () => Ce.value.find((e) => e.name === B.templateName) ?? { name: B.templateName }, - set: (e) => { - B.templateName = e.name; - } - }), cn = n(() => (k.value?.entries ?? []).filter((e) => e.currency_id === (O.value?.currency_id ?? null))), ln = n(() => { + }), F = n(() => (T.value?.entries ?? []).filter((e) => e.currency_id === (w.value?.currency_id ?? null))), I = n(() => { let e = {}; - for (let t of cn.value) e[t.id] = t; + for (let t of F.value) e[t.id] = t; return e; - }), un = n(() => (k.value?.groups[A.value] ?? []).filter((e) => e.currency_id === (O.value?.currency_id ?? null))), dn = n(() => cn.value.length), fn = n(() => dn.value > 0 && j.value.length === dn.value), pn = n(() => j.value.reduce((e, t) => e + (ln.value[t]?.minutes ?? 0), 0)), mn = n(() => j.value.reduce((e, t) => e + (ln.value[t]?.amount ?? 0), 0)), hn = n(() => O.value === null ? null : Dn(O.value.customer_id, O.value.currency_id)), gn = n(() => { - let e = N.value?.currency?.id ?? null; - return e === null || O.value === null ? !1 : En(O.value.customer_id) !== e; - }), _n = n(() => N.value?.autoGenerateNumber !== !0 || ue.value.invoice_number !== void 0), vn = n(() => { + }), L = n(() => (T.value?.groups?.[k.value] ?? []).filter((e) => e.currency_id === (w.value?.currency_id ?? null))), R = n(() => F.value.length), z = n(() => R.value > 0 && A.value.length === R.value), ee = n(() => A.value.reduce((e, t) => e + (I.value[t]?.minutes ?? 0), 0)), te = n(() => A.value.reduce((e, t) => e + (I.value[t]?.amount ?? 0), 0)), ne = n(() => { let e = {}; - return T.from !== "" && (e.from = T.from), T.to !== "" && (e.to = T.to), e; + return g.from !== "" && (e.from = g.from), g.to !== "" && (e.to = g.to), e; }); - E(() => [T.from, T.to], () => void Sn()), h(() => void yn()); - async function yn() { - m.value = !0, await Promise.all([ - xn(), - Sn(), - Cn(), - wn() - ]), m.value = !1; - let e = bn(); - if (e !== null) { - let t = g.value.find((t) => t.customer_id === e); - t && await jn(t); - } - } - function bn() { - let e = l.router.currentRoute.value.query.customer_id, t = Array.isArray(e) ? e[0] : e ?? new URLSearchParams(window.location.search).get("customer_id"), n = Number(t); - return Number.isInteger(n) && n > 0 ? n : null; - } - async function xn() { - try { - N.value = await oe(l.client); - } catch { - N.value = null; - } - } - async function Sn() { - try { - g.value = await I(l.client, vn.value); - } catch (e) { - g.value = [], l.notify("error", z(e, d("tasks_projects.billing.customer.load_failed"))); - } + E(() => [g.from, g.to], () => void ie()), h(() => void re()); + async function re() { + p.value = !0, await Promise.all([ae(), en(l.client)]), p.value = !1; } - async function Cn() { - try { - let e = {}; - for (let t of await te(l.client)) e[t.id] = t; - w.value = e; - } catch { - w.value = {}; - } + async function ie() { + await ae(), w.value !== null && await fe(w.value); } - async function wn() { + async function ae() { try { - P.value = await re(l.client); + m.value = await ue(l.client, ne.value); } catch (e) { - P.value = [], l.notify("error", z(e, d("tasks_projects.billing.preview.templates_failed"))); + m.value = [], l.notify("error", H(e, d("tasks_projects.billing.customer.load_failed"))); } } - function Tn(e) { - let t = w.value[e], n = t?.display_name ?? t?.name; - return n && n !== "" ? n : d("tasks_projects.billing.customer.unnamed", { id: e }); - } - function En(e) { - let t = w.value[e]; - return t?.currency_id ?? t?.currency?.id ?? null; - } - function Dn(e, t) { - if (t === null) return null; - let n = w.value[e]; - if (n?.currency && n.currency.id === t) return n.currency; - let r = N.value?.currency ?? null; - return r !== null && r.id === t ? r : null; + function oe(e) { + return $t(e); } - function On() { - T.from = "", T.to = ""; + function se() { + g.from = "", g.to = ""; } - function kn(e) { - T.from = e ? _e(e) : ""; + function ce(e) { + g.from = e ? dt(e) : ""; } - function An(e) { - T.to = e ? _e(e) : ""; + function le(e) { + g.to = e ? dt(e) : ""; } - async function jn(e) { - O.value = e, p.value = 2, M.value = !0, k.value = null, j.value = []; + async function fe(e) { + w.value = e, O.value = !0, T.value = null, A.value = []; try { - k.value = await L(l.client, e.customer_id, vn.value), j.value = cn.value.map((e) => e.id); + T.value = await de(l.client, e.customer_id, ne.value), A.value = F.value.map((e) => e.id); } catch (e) { - l.notify("error", z(e, d("tasks_projects.billing.entries.load_failed"))); + l.notify("error", H(e, d("tasks_projects.billing.entries.load_failed"))); } finally { - M.value = !1; + O.value = !1; } } - function Mn(e) { - return j.value.includes(e); + function pe() { + w.value = null, T.value = null, A.value = [], ae(); } - function Nn(e) { - j.value = Mn(e) ? j.value.filter((t) => t !== e) : [...j.value, e]; + function me(e) { + return A.value.includes(e); } - function Pn() { - j.value = fn.value ? [] : cn.value.map((e) => e.id); + function he(e) { + A.value = me(e) ? A.value.filter((t) => t !== e) : [...A.value, e]; } - function Fn(e) { - return e.entry_ids.length > 0 && e.entry_ids.every((e) => Mn(e)); + function ge() { + A.value = z.value ? [] : F.value.map((e) => e.id); } - function In(e) { - if (Fn(e)) { - j.value = j.value.filter((t) => !e.entry_ids.includes(t)); - return; - } - let t = e.entry_ids.filter((e) => !Mn(e)); - j.value = [...j.value, ...t]; + function _e(e) { + return e.entry_ids.length > 0 && e.entry_ids.every((e) => me(e)); } - function Ln(e) { - return e.entry_ids.map((e) => ln.value[e]).filter((e) => e !== void 0); - } - async function Rn() { - if (j.value.length === 0) { - l.notify("warning", d("tasks_projects.billing.entries.none_selected")); + function ve(e) { + if (_e(e)) { + A.value = A.value.filter((t) => !e.entry_ids.includes(t)); return; } - p.value = 3, se.value = !0, F.value = null, ue.value = {}, de.value = !1; - try { - let e = await ee(l.client, j.value, A.value); - F.value = e, await zn(e); - } catch (e) { - l.notify("error", z(e, d("tasks_projects.billing.preview.prepare_failed"))), p.value = 2; - } finally { - se.value = !1; - } - } - async function zn(e) { - B.invoiceDate = e.invoice_date, B.dueDate = Bn(e.invoice_date), B.templateName = N.value?.defaultTemplate ?? P.value[0]?.name ?? ""; - let [t, n] = await Promise.all([ie(l.client, e.customer_id).catch(() => null), gn.value && O.value?.currency_id ? ae(l.client, O.value.currency_id).catch(() => null) : Promise.resolve(null)]); - B.invoiceNumber = t ?? "", t === null && l.notify("warning", d("tasks_projects.billing.preview.number_failed")), gn.value ? (B.exchangeRate = n === null ? "" : String(n), n === null && l.notify("warning", d("tasks_projects.billing.preview.rate_failed"))) : B.exchangeRate = ""; - } - function Bn(e) { - let t = N.value; - if (t === null || !t.setDueDateAutomatically) return ""; - let n = /* @__PURE__ */ new Date(`${e}T00:00:00`); - return Number.isNaN(n.getTime()) ? "" : (n.setDate(n.getDate() + t.dueDateDays), _e(n)); - } - function Vn(e) { - B.invoiceDate = e ? _e(e) : "", B.dueDate = Bn(B.invoiceDate); - } - function Hn(e) { - B.dueDate = e ? _e(e) : ""; + let t = e.entry_ids.filter((e) => !me(e)); + A.value = [...A.value, ...t]; } - function Un(e) { - return { - invoice_date: B.invoiceDate, - due_date: B.dueDate === "" ? null : B.dueDate, - customer_id: e.customer_id, - invoice_number: B.invoiceNumber, - currency_id: En(e.customer_id) ?? e.currency_id, - exchange_rate: gn.value && B.exchangeRate !== "" ? Number(B.exchangeRate) : null, - discount: e.discount, - discount_type: e.discount_type, - discount_val: e.discount_val, - tax: e.tax, - sub_total: e.sub_total, - total: e.total, - tax_included: !1, - notes: e.notes, - template_name: B.templateName, - items: e.items.map((e) => ({ ...e })), - taxes: [] - }; + function ye(e) { + return e.entry_ids.map((e) => I.value[e]).filter((e) => e !== void 0); } - async function Wn() { - let e = F.value; - if (!(e === null || fe.value)) { - p.value = 4, fe.value = !0, ue.value = {}, de.value = !1, pe.value = null, me.value = null, he.value = !1; - try { - let t = await ne(l.client, Un(e)); - pe.value = t, await Gn(t, e); - } catch (e) { - le(e) === 422 ? (ue.value = ce(e), de.value = !0, p.value = 3, l.notify("error", z(e, d("tasks_projects.billing.preview.invalid")))) : (p.value = 3, l.notify("error", z(e, d("tasks_projects.billing.create.failed")))); - } finally { - fe.value = !1; - } - } - } - async function Gn(e, t) { - let n = e.items ?? [], r = []; - if (t.groups.forEach((e, t) => { - let i = n[t]; - i && r.push({ - invoice_item_id: i.id, - entry_ids: e.entry_ids - }); - }), r.length === 0) { - he.value = !0; + async function be() { + if (A.value.length === 0) { + l.notify("warning", d("tasks_projects.billing.entries.none_selected")); return; } - ye.value = !0; - try { - me.value = await R(l.client, e.id, r), he.value = !1; - } catch (e) { - he.value = !0, l.notify("error", z(e, d("tasks_projects.billing.create.stamp_failed_title"))); - } finally { - ye.value = !1; - } - } - async function Kn() { - let e = pe.value, t = F.value; - e === null || t === null || ye.value || (await Gn(e, t), he.value || l.notify("success", d("tasks_projects.billing.create.stamped"))); - } - async function qn() { - p.value = 1, O.value = null, k.value = null, F.value = null, pe.value = null, me.value = null, he.value = !1, j.value = [], ue.value = {}, de.value = !1, await Sn(); - } - function Jn(e) { - return p.value > e ? "border-primary-500 bg-primary-500 text-white" : p.value === e ? "border-primary-500 text-primary-500" : "border-line-default text-subtle"; + await bt({ + client: l.client, + router: l.router, + notify: l.notify, + t: d + }, { + entryIds: [...A.value], + grouping: k.value + }) || await ie(); } - return (t, n) => { - let l = x("BaseBreadcrumbItem"), u = x("BaseBreadcrumb"), h = x("BaseIcon"), v = x("BaseButton"), y = x("router-link"), w = x("BasePageHeader"), E = x("BaseSpinner"), k = x("BaseDatePicker"), A = x("BaseInputGroup"), N = x("BaseFormatMoney"), P = x("BaseEmptyPlaceholder"), I = x("BaseSelectInput"), L = x("BaseInput"), ee = x("BasePage"); - return _(), r(ee, null, { + return (n, l) => { + let u = x("BaseBreadcrumbItem"), h = x("BaseBreadcrumb"), v = x("BaseIcon"), y = x("BaseButton"), T = x("router-link"), E = x("BasePageHeader"), k = x("BaseDatePicker"), M = x("BaseInputGroup"), F = x("BaseSpinner"), I = x("BaseFormatMoney"), B = x("BaseEmptyPlaceholder"), ne = x("BaseSelectInput"), re = x("BasePage"); + return _(), r(re, null, { default: D(() => [ - c(w, { title: C(d)("tasks_projects.billing.title") }, { - actions: D(() => [o("div", Te, [c(y, { to: C(Se).week }, { - default: D(() => [c(v, { variant: "white" }, { - left: D((e) => [c(h, { - name: "ClockIcon", + c(E, { title: C(d)("tasks_projects.billing.title") }, { + actions: D(() => [o("div", ln, [c(T, { to: C(W).reports }, { + default: D(() => [c(y, { variant: "white" }, { + left: D((e) => [c(v, { + name: "ChartBarIcon", + class: f(e.class) + }, null, 8, ["class"])]), + default: D(() => [s(" " + S(C(d)("tasks_projects.reports.title")), 1)]), + _: 1 + })]), + _: 1 + }, 8, ["to"]), c(T, { to: C(W).projects }, { + default: D(() => [c(y, { variant: "white" }, { + left: D((e) => [c(v, { + name: "FolderIcon", class: f(e.class) }, null, 8, ["class"])]), - default: D(() => [s(" " + S(C(d)("tasks_projects.time.title")), 1)]), + default: D(() => [s(" " + S(C(d)("tasks_projects.projects.title")), 1)]), _: 1 })]), _: 1 }, 8, ["to"])])]), - default: D(() => [c(u, null, { + default: D(() => [c(h, null, { default: D(() => [ - c(l, { + c(u, { title: C(d)("tasks_projects.general.home"), to: "/admin/dashboard" }, null, 8, ["title"]), - c(l, { + c(u, { title: C(d)("tasks_projects.tasks.title"), - to: C(Se).tasks + to: C(W).tasks }, null, 8, ["title", "to"]), - c(l, { + c(u, { title: C(d)("tasks_projects.billing.title"), to: "#", active: "" }, null, 8, ["title"]) ]), _: 1 - })]), + }), o("p", cn, S(C(d)("tasks_projects.billing.subtitle")), 1)]), _: 1 }, 8, ["title"]), - o("ol", Ee, [(_(!0), a(e, null, b(be.value, (e, t) => (_(), a("li", { - key: e, - class: "flex items-center gap-2" - }, [o("span", { class: f(["flex h-7 w-7 items-center justify-center rounded-full border text-xs font-semibold", Jn(t + 1)]) }, S(t + 1), 3), o("span", { class: f(["text-sm font-medium", p.value === t + 1 ? "text-heading" : "text-muted"]) }, S(e), 3)]))), 128))]), - m.value ? (_(), a("div", De, [c(E, { class: "h-8 w-8 text-primary-500" })])) : p.value === 1 ? (_(), a("section", Oe, [ - o("h2", ke, S(C(d)("tasks_projects.billing.customer.title")), 1), - o("p", Ae, S(C(d)("tasks_projects.billing.customer.description")), 1), - o("div", je, [ - c(A, { - label: C(d)("tasks_projects.billing.customer.from"), - class: "w-full sm:w-48" - }, { - default: D(() => [c(k, { - "model-value": T.from, - "onUpdate:modelValue": kn - }, null, 8, ["model-value"])]), - _: 1 - }, 8, ["label"]), - c(A, { - label: C(d)("tasks_projects.billing.customer.to"), - class: "w-full sm:w-48" - }, { - default: D(() => [c(k, { - "model-value": T.to, - "onUpdate:modelValue": An - }, null, 8, ["model-value"])]), - _: 1 - }, 8, ["label"]), - T.from !== "" || T.to !== "" ? (_(), r(v, { - key: 0, - variant: "primary-outline", - onClick: On - }, { - default: D(() => [s(S(C(d)("tasks_projects.billing.customer.clear_range")), 1)]), - _: 1 - })) : i("", !0) - ]), - g.value.length > 0 ? (_(), a("div", Me, [(_(!0), a(e, null, b(g.value, (e) => (_(), a("button", { + c(Lt, { + client: t.client, + notify: t.notify + }, null, 8, ["client", "notify"]), + o("div", un, [ + c(M, { + label: C(d)("tasks_projects.billing.customer.from"), + class: "w-full sm:w-48" + }, { + default: D(() => [c(k, { + "model-value": g.from, + "onUpdate:modelValue": ce + }, null, 8, ["model-value"])]), + _: 1 + }, 8, ["label"]), + c(M, { + label: C(d)("tasks_projects.billing.customer.to"), + class: "w-full sm:w-48" + }, { + default: D(() => [c(k, { + "model-value": g.to, + "onUpdate:modelValue": le + }, null, 8, ["model-value"])]), + _: 1 + }, 8, ["label"]), + g.from !== "" || g.to !== "" ? (_(), r(y, { + key: 0, + variant: "primary-outline", + onClick: se + }, { + default: D(() => [s(S(C(d)("tasks_projects.billing.customer.clear_range")), 1)]), + _: 1 + })) : i("", !0) + ]), + p.value ? (_(), a("div", dn, [c(F, { class: "h-8 w-8 text-primary-500" })])) : w.value === null ? (_(), a("section", fn, [ + o("h2", pn, S(C(d)("tasks_projects.billing.customer.title")), 1), + o("p", mn, S(C(d)("tasks_projects.billing.customer.description")), 1), + m.value.length > 0 ? (_(), a("div", hn, [(_(!0), a(e, null, b(m.value, (e) => (_(), a("button", { key: `${e.customer_id}-${e.currency_id ?? "none"}`, type: "button", class: "rounded-xl border border-line-default bg-surface p-5 text-left transition hover:border-primary-500", - onClick: (t) => jn(e) + onClick: (t) => fe(e) }, [ - o("p", Pe, S(Tn(e.customer_id)), 1), - o("p", Fe, S(C(d)("tasks_projects.billing.customer.entries", { count: e.entries })) + " · " + S(C(ve)(e.minutes)), 1), - o("p", Ie, [c(N, { - amount: e.amount, - currency: Dn(e.customer_id, e.currency_id) - }, null, 8, ["amount", "currency"])]) - ], 8, Ne))), 128))])) : (_(), r(P, { + o("p", _n, S(oe(e.customer_id)), 1), + o("p", vn, S(C(d)("tasks_projects.billing.customer.entries", { count: e.entries })) + " · " + S(C(ft)(e.minutes)), 1), + o("p", yn, [c(I, { amount: e.amount }, null, 8, ["amount"])]) + ], 8, gn))), 128))])) : (_(), r(B, { key: 1, title: C(d)("tasks_projects.billing.customer.empty_title"), description: C(d)("tasks_projects.billing.customer.empty_description") }, { - default: D(() => [c(h, { + default: D(() => [c(v, { name: "BanknotesIcon", class: "mt-5 mb-4 h-16 w-16 text-subtle" })]), _: 1 }, 8, ["title", "description"])) - ])) : p.value === 2 ? (_(), a("section", Le, [o("div", Re, [o("div", null, [o("h2", ze, S(C(d)("tasks_projects.billing.entries.title")), 1), o("p", Be, S(O.value ? Tn(O.value.customer_id) : ""), 1)]), c(A, { + ])) : (_(), a("section", bn, [o("div", xn, [o("div", null, [o("h2", Sn, S(C(d)("tasks_projects.billing.entries.title")), 1), o("p", Cn, S(oe(w.value.customer_id)), 1)]), c(M, { label: C(d)("tasks_projects.billing.entries.grouping"), class: "w-full sm:w-56" }, { - default: D(() => [c(I, { - modelValue: xe.value, - "onUpdate:modelValue": n[0] ||= (e) => xe.value = e, - options: H.value, + default: D(() => [c(ne, { + modelValue: P.value, + "onUpdate:modelValue": l[0] ||= (e) => P.value = e, + options: N.value, "label-key": "label" }, null, 8, ["modelValue", "options"])]), _: 1 - }, 8, ["label"])]), M.value ? (_(), a("div", Ve, [c(E, { class: "h-8 w-8 text-primary-500" })])) : dn.value > 0 ? (_(), a(e, { key: 1 }, [ - o("div", He, [o("label", Ue, [o("input", { + }, 8, ["label"])]), O.value ? (_(), a("div", wn, [c(F, { class: "h-8 w-8 text-primary-500" })])) : R.value > 0 ? (_(), a(e, { key: 1 }, [ + o("div", Tn, [o("label", En, [o("input", { type: "checkbox", class: "h-4 w-4 cursor-pointer rounded border-line-strong", - checked: fn.value, - onChange: Pn - }, null, 40, We), s(" " + S(C(d)("tasks_projects.billing.entries.select_all")), 1)]), o("p", Ge, S(C(d)("tasks_projects.billing.entries.selected", { - count: j.value.length, - total: dn.value + checked: z.value, + onChange: ge + }, null, 40, Dn), s(" " + S(C(d)("tasks_projects.billing.entries.select_all")), 1)]), o("p", On, S(C(d)("tasks_projects.billing.entries.selected", { + count: A.value.length, + total: R.value })), 1)]), - (_(!0), a(e, null, b(un.value, (t) => (_(), a("div", { + (_(!0), a(e, null, b(L.value, (t) => (_(), a("div", { key: `${t.label}-${t.key ?? "none"}-${t.currency_id ?? "none"}`, class: "mt-4 overflow-hidden rounded-xl border border-line-default" - }, [o("div", Ke, [o("label", qe, [o("input", { + }, [o("div", kn, [o("label", An, [o("input", { type: "checkbox", class: "h-4 w-4 cursor-pointer rounded border-line-strong", - checked: Fn(t), - onChange: (e) => In(t) - }, null, 40, Je), s(" " + S(t.label), 1)]), o("p", Ye, [s(S(C(ve)(t.minutes)) + " · ", 1), c(N, { - amount: t.amount, - currency: hn.value - }, null, 8, ["amount", "currency"])])]), o("div", Xe, [o("table", Ze, [o("thead", Qe, [o("tr", null, [ - n[6] ||= o("th", { class: "w-10" }, null, -1), - o("th", $e, S(C(d)("tasks_projects.billing.entries.columns.date")), 1), - o("th", et, S(C(d)("tasks_projects.billing.entries.columns.task")), 1), - o("th", tt, S(C(d)("tasks_projects.billing.entries.columns.project")), 1), - o("th", nt, S(C(d)("tasks_projects.billing.entries.columns.member")), 1), - o("th", rt, S(C(d)("tasks_projects.billing.entries.columns.duration")), 1), - o("th", it, S(C(d)("tasks_projects.billing.entries.columns.amount")), 1) - ])]), o("tbody", at, [(_(!0), a(e, null, b(Ln(t), (e) => (_(), a("tr", { key: e.id }, [ - o("td", ot, [o("input", { + checked: _e(t), + onChange: (e) => ve(t) + }, null, 40, jn), s(" " + S(t.label), 1)]), o("p", Mn, [s(S(C(ft)(t.minutes)) + " · ", 1), c(I, { amount: t.amount }, null, 8, ["amount"])])]), o("div", Nn, [o("table", Pn, [o("thead", Fn, [o("tr", null, [ + l[1] ||= o("th", { class: "w-10" }, null, -1), + o("th", In, S(C(d)("tasks_projects.billing.entries.columns.date")), 1), + o("th", Ln, S(C(d)("tasks_projects.billing.entries.columns.task")), 1), + o("th", Rn, S(C(d)("tasks_projects.billing.entries.columns.project")), 1), + o("th", zn, S(C(d)("tasks_projects.billing.entries.columns.member")), 1), + o("th", Bn, S(C(d)("tasks_projects.billing.entries.columns.duration")), 1), + o("th", Vn, S(C(d)("tasks_projects.billing.entries.columns.amount")), 1) + ])]), o("tbody", Hn, [(_(!0), a(e, null, b(ye(t), (e) => (_(), a("tr", { key: e.id }, [ + o("td", Un, [o("input", { type: "checkbox", class: "h-4 w-4 cursor-pointer rounded border-line-strong", - checked: Mn(e.id), - onChange: (t) => Nn(e.id) - }, null, 40, st)]), - o("td", ct, S(C(ge)(e.date)), 1), - o("td", lt, [o("span", ut, S(e.task_name), 1), o("span", dt, S(e.description || C(d)("tasks_projects.billing.entries.no_description")), 1)]), - o("td", ft, S(e.project_name ?? "-"), 1), - o("td", pt, S(e.user_name), 1), - o("td", mt, S(C(ve)(e.minutes)), 1), - o("td", ht, [c(N, { - amount: e.amount, - currency: hn.value - }, null, 8, ["amount", "currency"])]) + checked: me(e.id), + onChange: (t) => he(e.id) + }, null, 40, Wn)]), + o("td", Gn, S(C(ut)(e.date)), 1), + o("td", Kn, [c(T, { + class: "text-heading hover:text-primary-500", + to: C(W).task(e.task_id) + }, { + default: D(() => [s(S(e.task_name), 1)]), + _: 2 + }, 1032, ["to"]), o("span", qn, S(e.description || C(d)("tasks_projects.billing.entries.no_description")), 1)]), + o("td", Jn, S(e.project_name ?? "-"), 1), + o("td", Yn, S(e.user_name), 1), + o("td", Xn, S(C(ft)(e.minutes)), 1), + o("td", Zn, [c(I, { amount: e.amount }, null, 8, ["amount"])]) ]))), 128))])])])]))), 128)), - o("div", gt, [o("p", _t, [s(S(C(d)("tasks_projects.billing.entries.selected_total", { hours: C(ve)(pn.value) })) + " · ", 1), c(N, { - amount: mn.value, - currency: hn.value - }, null, 8, ["amount", "currency"])]), o("div", vt, [c(v, { + o("div", Qn, [o("p", $n, [s(S(C(d)("tasks_projects.billing.entries.selected_total", { hours: C(ft)(ee.value) })) + " · ", 1), c(I, { amount: te.value }, null, 8, ["amount"])]), o("div", er, [c(y, { variant: "primary-outline", - onClick: qn + disabled: j.value, + onClick: pe }, { default: D(() => [s(S(C(d)("tasks_projects.billing.back")), 1)]), _: 1 - }), c(v, { + }, 8, ["disabled"]), c(y, { variant: "primary", - disabled: j.value.length === 0, - onClick: Rn + loading: j.value, + disabled: j.value || A.value.length === 0, + onClick: be }, { - default: D(() => [s(S(C(d)("tasks_projects.billing.next")), 1)]), + left: D((e) => [j.value ? i("", !0) : (_(), r(v, { + key: 0, + name: "DocumentPlusIcon", + class: f(e.class) + }, null, 8, ["class"]))]), + default: D(() => [s(" " + S(C(d)("tasks_projects.billing.create")), 1)]), _: 1 - }, 8, ["disabled"])])]) - ], 64)) : (_(), r(P, { + }, 8, ["loading", "disabled"])])]) + ], 64)) : (_(), r(B, { key: 2, title: C(d)("tasks_projects.billing.entries.empty_title"), description: C(d)("tasks_projects.billing.entries.empty_description") }, { - actions: D(() => [c(v, { + actions: D(() => [c(y, { variant: "primary", - onClick: qn + onClick: pe }, { default: D(() => [s(S(C(d)("tasks_projects.billing.back")), 1)]), _: 1 })]), - default: D(() => [c(h, { + default: D(() => [c(v, { name: "ClockIcon", class: "mt-5 mb-4 h-16 w-16 text-subtle" })]), _: 1 - }, 8, ["title", "description"]))])) : p.value === 3 ? (_(), a("section", yt, [o("h2", bt, S(C(d)("tasks_projects.billing.preview.title")), 1), se.value || F.value === null ? (_(), a("div", xt, [c(E, { class: "h-8 w-8 text-primary-500" })])) : (_(), a(e, { key: 1 }, [ - de.value ? (_(), a("div", St, S(C(d)("tasks_projects.billing.preview.invalid")), 1)) : i("", !0), - o("div", Ct, [ - c(A, { - label: C(d)("tasks_projects.billing.preview.invoice_date"), - error: ue.value.invoice_date, - required: "" - }, { - default: D(() => [c(k, { - "model-value": B.invoiceDate, - "onUpdate:modelValue": Vn - }, null, 8, ["model-value"])]), - _: 1 - }, 8, ["label", "error"]), - c(A, { - label: C(d)("tasks_projects.billing.preview.due_date"), - error: ue.value.due_date - }, { - default: D(() => [c(k, { - "model-value": B.dueDate, - "onUpdate:modelValue": Hn - }, null, 8, ["model-value"])]), - _: 1 - }, 8, ["label", "error"]), - c(A, { - label: C(d)("tasks_projects.billing.preview.invoice_number"), - error: ue.value.invoice_number, - required: "" - }, { - default: D(() => [c(L, { - modelValue: B.invoiceNumber, - "onUpdate:modelValue": n[1] ||= (e) => B.invoiceNumber = e, - type: "text", - name: "invoice_number", - disabled: !_n.value - }, null, 8, ["modelValue", "disabled"]), _n.value ? i("", !0) : (_(), a("span", wt, S(C(d)("tasks_projects.billing.preview.invoice_number_auto")), 1))]), - _: 1 - }, 8, ["label", "error"]), - c(A, { - label: C(d)("tasks_projects.billing.preview.template"), - error: ue.value.template_name, - required: "" - }, { - default: D(() => [c(I, { - modelValue: we.value, - "onUpdate:modelValue": n[2] ||= (e) => we.value = e, - options: Ce.value, - "label-key": "name" - }, null, 8, ["modelValue", "options"])]), - _: 1 - }, 8, ["label", "error"]), - gn.value ? (_(), r(A, { - key: 0, - label: C(d)("tasks_projects.billing.preview.exchange_rate"), - error: ue.value.exchange_rate, - required: "" - }, { - default: D(() => [c(L, { - modelValue: B.exchangeRate, - "onUpdate:modelValue": n[3] ||= (e) => B.exchangeRate = e, - type: "text", - name: "exchange_rate" - }, null, 8, ["modelValue"]), o("span", Tt, S(C(d)("tasks_projects.billing.preview.exchange_rate_help", { currency: hn.value?.code ?? "" })), 1)]), - _: 1 - }, 8, ["label", "error"])) : i("", !0) - ]), - o("div", Et, [o("div", Dt, [o("table", Ot, [ - o("thead", kt, [o("tr", null, [ - o("th", At, S(C(d)("tasks_projects.billing.preview.columns.description")), 1), - o("th", jt, S(C(d)("tasks_projects.billing.preview.columns.quantity")), 1), - o("th", Mt, S(C(d)("tasks_projects.billing.preview.columns.price")), 1), - o("th", Nt, S(C(d)("tasks_projects.billing.preview.columns.total")), 1) - ])]), - o("tbody", Pt, [(_(!0), a(e, null, b(F.value.items, (e, t) => (_(), a("tr", { key: `${e.name}-${t}` }, [ - o("td", Ft, [o("span", It, S(e.name), 1), e.description ? (_(), a("span", Lt, S(e.description), 1)) : i("", !0)]), - o("td", Rt, S(e.quantity), 1), - o("td", zt, [c(N, { - amount: e.price, - currency: hn.value - }, null, 8, ["amount", "currency"])]), - o("td", Bt, [c(N, { - amount: e.total, - currency: hn.value - }, null, 8, ["amount", "currency"])]) - ]))), 128))]), - o("tfoot", Vt, [o("tr", null, [o("td", Ht, S(C(d)("tasks_projects.billing.preview.sub_total")), 1), o("td", Ut, [c(N, { - amount: F.value.sub_total, - currency: hn.value - }, null, 8, ["amount", "currency"])])]), o("tr", null, [o("td", Wt, S(C(d)("tasks_projects.billing.preview.total")), 1), o("td", Gt, [c(N, { - amount: F.value.total, - currency: hn.value - }, null, 8, ["amount", "currency"])])])]) - ])])]), - o("div", Kt, [c(v, { - variant: "primary-outline", - onClick: n[4] ||= (e) => p.value = 2 - }, { - default: D(() => [s(S(C(d)("tasks_projects.billing.back")), 1)]), - _: 1 - }), c(v, { - variant: "primary", - loading: fe.value, - disabled: fe.value, - onClick: Wn - }, { - left: D((e) => [fe.value ? i("", !0) : (_(), r(h, { - key: 0, - name: "DocumentPlusIcon", - class: f(e.class) - }, null, 8, ["class"]))]), - default: D(() => [s(" " + S(C(d)("tasks_projects.billing.preview.create")), 1)]), - _: 1 - }, 8, ["loading", "disabled"])]) - ], 64))])) : (_(), a("section", qt, [fe.value || ye.value ? (_(), a("div", Jt, [c(E, { class: "h-8 w-8 text-primary-500" }), o("p", Yt, S(fe.value ? C(d)("tasks_projects.billing.create.creating") : C(d)("tasks_projects.billing.create.stamping")), 1)])) : pe.value ? (_(), a(e, { key: 1 }, [he.value ? (_(), a("div", Xt, [ - o("p", Zt, S(C(d)("tasks_projects.billing.create.stamp_failed_title")), 1), - o("p", Qt, S(C(d)("tasks_projects.billing.create.stamp_failed_description", { number: pe.value.invoice_number })), 1), - o("div", $t, [c(v, { - variant: "primary", - loading: ye.value, - onClick: Kn - }, { - default: D(() => [s(S(C(d)("tasks_projects.billing.create.retry_stamp")), 1)]), - _: 1 - }, 8, ["loading"]), c(y, { to: `${sn}/${pe.value.id}/view` }, { - default: D(() => [c(v, { variant: "white" }, { - default: D(() => [s(S(C(d)("tasks_projects.billing.create.view_invoice")), 1)]), - _: 1 - })]), - _: 1 - }, 8, ["to"])]) - ])) : (_(), a("div", en, [ - c(h, { - name: "CheckCircleIcon", - class: "mx-auto h-12 w-12 text-primary-500" - }), - o("p", tn, S(C(d)("tasks_projects.billing.create.created_title", { number: pe.value.invoice_number })), 1), - o("p", nn, S(C(d)("tasks_projects.billing.create.created_description", { count: me.value ?? 0 })), 1), - o("p", rn, [c(N, { - amount: pe.value.total, - currency: hn.value - }, null, 8, ["amount", "currency"])]), - o("div", an, [c(y, { to: `${sn}/${pe.value.id}/view` }, { - default: D(() => [c(v, { variant: "primary" }, { - default: D(() => [s(S(C(d)("tasks_projects.billing.create.view_invoice")), 1)]), - _: 1 - })]), - _: 1 - }, 8, ["to"]), c(v, { - variant: "white", - onClick: qn - }, { - default: D(() => [s(S(C(d)("tasks_projects.billing.create.invoice_more")), 1)]), - _: 1 - })]) - ]))], 64)) : (_(), a("div", on, [c(v, { - variant: "primary-outline", - onClick: n[5] ||= (e) => p.value = 3 - }, { - default: D(() => [s(S(C(d)("tasks_projects.billing.back")), 1)]), - _: 1 - })]))])) + }, 8, ["title", "description"]))])) ]), _: 1 }); }; } -}), ln = "tasks-projects"; -function un(e) { - e.addMessages(M), e.registerPage({ +}); +//#endregion +//#region resources/js/registrations/billing.ts +function nr(e) { + e.addMessages(oe), e.registerPage({ id: "billing", - module: ln, + module: U, path: "billing", - component: we(e, cn), + component: sn(e, tr), meta: { - ability: `${ln}:invoice-tasks`, + ability: `${U}:invoice-tasks`, title: "tasks_projects.billing.title" } + }), e.registerCompanyLayoutOverlay({ + id: `${U}.invoice-number`, + component: l({ setup: () => () => d(ae) }) + }), e.on("company:changing", () => { + ee(); }); } //#endregion //#region resources/js/messages/projects.ts -var dn = { en: { tasks_projects: { project: { +var rr = { en: { tasks_projects: { project: { load_failed: "Unable to load the project.", customer: "Customer", identifier: "Identifier", @@ -1023,7 +1199,6 @@ var dn = { en: { tasks_projects: { project: { board: "Board", tasks: "Tasks", invoice_project: "Invoice project", - invoice_soon: "Coming with invoicing", tabs: { overview: "Overview", tasks: "Tasks", @@ -1076,141 +1251,92 @@ var dn = { en: { tasks_projects: { project: { attach_failed: "Unable to add the member.", detach_failed: "Unable to remove the member." } -} } } }, fn = "/api/v1/tasks-projects", pn = { - projects: `${fn}/projects`, - project: (e) => `${fn}/projects/${e}`, - archiveProject: (e) => `${fn}/projects/${e}/archive`, - unarchiveProject: (e) => `${fn}/projects/${e}/unarchive`, - members: `${fn}/members`, - settings: `${fn}/settings` -}, mn = { customers: "/api/v1/customers" }; -function hn(e, t) { - if (e === void 0 || e.order === "") return {}; - let n = t[e.fieldName]; - return n === void 0 ? {} : { - sort_by: n, - sort_order: e.order - }; -} -async function gn(e, t) { - let { data: n } = await e.get(pn.projects, { params: t }); - return n; -} -async function _n(e, t) { - let { data: n } = await e.post(pn.projects, t); - return n.data; -} -async function vn(e, t, n) { - let { data: r } = await e.put(pn.project(t), n); - return r.data; -} -async function yn(e, t) { - let { data: n } = await e.post(pn.archiveProject(t)); - return n.data; -} -async function bn(e, t) { - let { data: n } = await e.post(pn.unarchiveProject(t)); - return n.data; -} -async function xn(e, t) { - await e.delete(pn.project(t)); -} -async function Sn(e) { - let { data: t } = await e.get(pn.members); - return t.data; -} -async function Cn(e, t = 100) { - let { data: n } = await e.get(mn.customers, { params: { limit: t } }); - return n.data; -} -//#endregion -//#region resources/js/api/board.ts -var wn = { - board: `${fn}/board`, - tasks: `${fn}/tasks`, - task: (e) => `${fn}/tasks/${e}`, - moveTask: (e) => `${fn}/tasks/${e}/move`, - startTask: (e) => `${fn}/tasks/${e}/start`, - stopTask: (e) => `${fn}/tasks/${e}/stop`, - taskTimeLog: (e) => `${fn}/tasks/${e}/time-log`, - bulkTasks: `${fn}/tasks/bulk`, - taskStatuses: `${fn}/task-statuses`, - timeEntries: `${fn}/time-entries`, - projectMembers: (e) => `${fn}/projects/${e}/members`, - projectMember: (e, t) => `${fn}/projects/${e}/members/${t}` +} } } }, ir = { + board: `${Rt}/board`, + tasks: `${Rt}/tasks`, + task: (e) => `${Rt}/tasks/${e}`, + moveTask: (e) => `${Rt}/tasks/${e}/move`, + startTask: (e) => `${Rt}/tasks/${e}/start`, + stopTask: (e) => `${Rt}/tasks/${e}/stop`, + taskTimeLog: (e) => `${Rt}/tasks/${e}/time-log`, + bulkTasks: `${Rt}/tasks/bulk`, + taskStatuses: `${Rt}/task-statuses`, + timeEntries: `${Rt}/time-entries`, + projectMembers: (e) => `${Rt}/projects/${e}/members`, + projectMember: (e, t) => `${Rt}/projects/${e}/members/${t}` }; -async function Tn(e, t) { - let { data: n } = await e.get(wn.board, { params: t }); +async function ar(e, t) { + let { data: n } = await e.get(ir.board, { params: t }); return n.data; } -async function En(e) { - let { data: t } = await e.get(wn.taskStatuses); +async function or(e) { + let { data: t } = await e.get(ir.taskStatuses); return t.data; } -async function Dn(e, t) { - let { data: n } = await e.get(wn.tasks, { params: t }); +async function sr(e, t) { + let { data: n } = await e.get(ir.tasks, { params: t }); return n; } -async function On(e, t) { - let { data: n } = await e.post(wn.tasks, t); +async function cr(e, t) { + let { data: n } = await e.post(ir.tasks, t); return n.data; } -async function kn(e, t, n) { - let { data: r } = await e.put(wn.task(t), n); +async function lr(e, t, n) { + let { data: r } = await e.put(ir.task(t), n); return r.data; } -async function An(e, t) { - await e.delete(wn.task(t)); +async function ur(e, t) { + await e.delete(ir.task(t)); } -async function jn(e, t) { - let { data: n } = await e.get(wn.task(t)); +async function dr(e, t) { + let { data: n } = await e.get(ir.task(t)); return n.data; } -async function Mn(e, t, n = null) { - let r = n === null ? {} : { description: n }, { data: i } = await e.post(wn.startTask(t), r); +async function fr(e, t, n = null) { + let r = n === null ? {} : { description: n }, { data: i } = await e.post(ir.startTask(t), r); return i.data; } -async function Nn(e, t) { - let { data: n } = await e.post(wn.stopTask(t)); +async function pr(e, t) { + let { data: n } = await e.post(ir.stopTask(t)); return n.data; } -async function Pn(e, t) { - let { data: n } = await e.get(wn.taskTimeLog(t)); +async function mr(e, t) { + let { data: n } = await e.get(ir.taskTimeLog(t)); return n.data ?? []; } -async function Fn(e, t) { - let { data: n } = await e.post(wn.bulkTasks, t); +async function hr(e, t) { + let { data: n } = await e.post(ir.bulkTasks, t); return { updated: n?.updated ?? 0, failed: n?.failed ?? [] }; } -async function In(e, t, n) { - let { data: r } = await e.post(wn.moveTask(t), n); +async function gr(e, t, n) { + let { data: r } = await e.post(ir.moveTask(t), n); return r.data; } -async function Ln(e, t) { - let { data: n } = await e.get(pn.project(t)); +async function _r(e, t) { + let { data: n } = await e.get(zt.project(t)); return n.data; } -async function Rn(e, t) { - let { data: n } = await e.get(wn.projectMembers(t)); +async function vr(e, t) { + let { data: n } = await e.get(ir.projectMembers(t)); return n.data; } -async function zn(e, t, n) { - let { data: r } = await e.post(wn.projectMembers(t), n); +async function yr(e, t, n) { + let { data: r } = await e.post(ir.projectMembers(t), n); return r.data; } -async function Bn(e, t, n) { - await e.delete(wn.projectMember(t, n)); +async function br(e, t, n) { + await e.delete(ir.projectMember(t, n)); } -async function Vn(e, t) { - let { data: n } = await e.get(wn.timeEntries, { params: t }); +async function xr(e, t) { + let { data: n } = await e.get(ir.timeEntries, { params: t }); return n; } //#endregion //#region resources/js/components/ProjectFormModal.vue?vue&type=script&setup=true&lang.ts -var Hn = { class: "flex w-full items-center justify-between" }, Un = { class: "space-y-5 px-6 py-6" }, Wn = { class: "flex flex-wrap items-center gap-2" }, Gn = ["aria-label", "onClick"], Kn = { class: "flex justify-end space-x-3 border-t border-line-default px-6 py-4" }, qn = /* @__PURE__ */ l({ +var Sr = { class: "flex w-full items-center justify-between" }, Cr = { class: "space-y-5 px-6 py-6" }, wr = { class: "flex flex-wrap items-center gap-2" }, Tr = ["aria-label", "onClick"], Er = { class: "flex justify-end space-x-3 border-t border-line-default px-6 py-4" }, Dr = /* @__PURE__ */ l({ __name: "ProjectFormModal", props: { show: { type: Boolean }, @@ -1229,7 +1355,7 @@ var Hn = { class: "flex w-full items-center justify-between" }, Un = { class: "s "#dc2626", "#7c3aed", "#64748b" - ], m = V(), h = v({ + ], m = B(), h = v({ name: "", identifier: "", description: "", @@ -1243,7 +1369,7 @@ var Hn = { class: "flex w-full items-center justify-between" }, Un = { class: "s }, { immediate: !0 }); function N() { let e = l.project; - h.name = e?.name ?? "", h.identifier = e?.identifier ?? "", h.description = e?.description ?? "", h.colour = e?.colour ?? "", h.defaultRate = fe(e?.default_rate ?? null), h.budgetHours = me(e?.budget_minutes ?? null), h.dueDate = e?.due_date ?? "", O.value = {}, g.value = P(e?.customer_id ?? null); + h.name = e?.name ?? "", h.identifier = e?.identifier ?? "", h.description = e?.description ?? "", h.colour = e?.colour ?? "", h.defaultRate = ot(e?.default_rate ?? null), h.budgetHours = ct(e?.budget_minutes ?? null), h.dueDate = e?.due_date ?? "", O.value = {}, g.value = P(e?.customer_id ?? null); } function P(e) { return e === null ? null : w.value.find((t) => t.id === e) ?? null; @@ -1253,13 +1379,13 @@ var Hn = { class: "flex w-full items-center justify-between" }, Un = { class: "s } async function I() { if (!T.value) try { - let e = await Cn(l.client); + let e = await Yt(l.client); w.value = e.map((e) => ({ id: e.id, label: F(e) })), T.value = !0, g.value = P(l.project?.customer_id ?? null); } catch (e) { - l.notify("error", z(e, m("tasks_projects.projects.customers_failed"))); + l.notify("error", H(e, m("tasks_projects.projects.customers_failed"))); } } function L() { @@ -1269,15 +1395,15 @@ var Hn = { class: "flex w-full items-center justify-between" }, Un = { class: "s identifier: h.identifier.trim() || null, description: h.description.trim() || null, colour: h.colour || null, - default_rate: pe(h.defaultRate), - budget_minutes: he(h.budgetHours), + default_rate: st(h.defaultRate), + budget_minutes: lt(h.budgetHours), due_date: h.dueDate || null }; } - function ee(e) { - h.dueDate = e ? _e(e) : ""; + function R(e) { + h.dueDate = e ? dt(e) : ""; } - async function R() { + async function z() { if (!k.value) { if (h.name.trim() === "") { O.value = { name: m("tasks_projects.projects.name_required") }; @@ -1285,10 +1411,10 @@ var Hn = { class: "flex w-full items-center justify-between" }, Un = { class: "s } k.value = !0, O.value = {}; try { - let e = l.project, t = e ? await vn(l.client, e.id, L()) : await _n(l.client, L()); + let e = l.project, t = e ? await Wt(l.client, e.id, L()) : await Ut(l.client, L()); u("saved", t); } catch (e) { - O.value = ce(e), l.notify("error", z(e, m("tasks_projects.projects.save_failed"))); + O.value = at(e), l.notify("error", H(e, m("tasks_projects.projects.save_failed"))); } finally { k.value = !1; } @@ -1300,12 +1426,12 @@ var Hn = { class: "flex w-full items-center justify-between" }, Un = { class: "s show: t.show, onClose: i[9] ||= (e) => u("close") }, { - header: D(() => [o("div", Hn, [o("span", null, S(M.value), 1), c(l, { + header: D(() => [o("div", Sr, [o("span", null, S(M.value), 1), c(l, { name: "XMarkIcon", class: "h-6 w-6 cursor-pointer text-subtle hover:text-body", onClick: i[0] ||= (e) => u("close") })])]), - default: D(() => [o("form", { onSubmit: A(R, ["prevent"]) }, [o("div", Un, [ + default: D(() => [o("form", { onSubmit: A(z, ["prevent"]) }, [o("div", Cr, [ c(N, null, { default: D(() => [ c(y, { @@ -1367,7 +1493,7 @@ var Hn = { class: "flex w-full items-center justify-between" }, Un = { class: "s }, { default: D(() => [c(E, { "model-value": h.dueDate, - "onUpdate:modelValue": ee + "onUpdate:modelValue": R }, null, 8, ["model-value"])]), _: 1 }, 8, ["label", "error"]), @@ -1411,14 +1537,14 @@ var Hn = { class: "flex w-full items-center justify-between" }, Un = { class: "s label: C(m)("tasks_projects.projects.fields.colour"), error: O.value.colour }, { - default: D(() => [o("div", Wn, [(_(), a(e, null, b(d, (e) => o("button", { + default: D(() => [o("div", wr, [(_(), a(e, null, b(d, (e) => o("button", { key: e, type: "button", class: f(["h-7 w-7 rounded-full border-2 transition", h.colour === e ? "border-heading" : "border-line-default"]), style: p({ backgroundColor: e }), "aria-label": e, onClick: (t) => h.colour = h.colour === e ? "" : e - }, null, 14, Gn)), 64)), o("button", { + }, null, 14, Tr)), 64)), o("button", { type: "button", class: "rounded-md border border-line-default px-2 py-1 text-xs text-muted hover:bg-hover", onClick: i[6] ||= (e) => h.colour = "" @@ -1437,7 +1563,7 @@ var Hn = { class: "flex w-full items-center justify-between" }, Un = { class: "s }, null, 8, ["modelValue", "invalid"])]), _: 1 }, 8, ["label", "error"]) - ]), o("div", Kn, [c(F, { + ]), o("div", Er, [c(F, { type: "button", variant: "primary-outline", onClick: i[8] ||= (e) => u("close") @@ -1457,53 +1583,23 @@ var Hn = { class: "flex w-full items-center justify-between" }, Un = { class: "s }, 8, ["show"]); }; } -}), Jn = v({}), Yn = !1, Xn = null; -function Zn(e) { - return e === null ? "" : Jn[e] ?? `#${e}`; -} -async function Qn(e) { - Yn || (Xn ??= er(e), await Xn); -} -function $n() { - for (let e of Object.keys(Jn)) delete Jn[Number(e)]; - Yn = !1, Xn = null; -} -async function er(e) { - try { - for (let t of await Cn(e, 200)) { - let e = t?.id; - typeof e == "number" && (Jn[e] = tr(t)); - } - Yn = !0; - } catch {} finally { - Xn = null; - } -} -function tr(e) { - let t = typeof e.display_name == "string" ? e.display_name.trim() : ""; - if (t !== "") return t; - let n = typeof e.name == "string" ? e.name.trim() : ""; - return n === "" ? `#${e.id}` : n; -} -//#endregion -//#region resources/js/pages/ProjectDetailPage.vue?vue&type=script&setup=true&lang.ts -var nr = { +}), Or = { key: 0, class: "mt-2 flex flex-wrap items-center gap-3 text-sm text-muted" -}, rr = { +}, kr = { key: 0, class: "rounded-sm bg-surface-tertiary px-2 py-0.5 text-body" -}, ir = { key: 1 }, ar = { class: "text-body" }, or = { +}, Ar = { key: 1 }, jr = { class: "text-body" }, Mr = { key: 2, class: "text-subtle" -}, sr = { key: 3 }, cr = { class: "text-body" }, lr = { class: "flex items-center justify-end space-x-5" }, ur = { class: "mt-6 flex overflow-x-auto border-b border-line-default" }, dr = [ +}, Nr = { key: 3 }, Pr = { class: "text-body" }, Fr = { class: "flex items-center justify-end space-x-5" }, Ir = { class: "mt-6 flex overflow-x-auto border-b border-line-default" }, Lr = [ "href", "aria-current", "onClick" -], fr = { +], Rr = { key: 0, class: "flex justify-center py-16" -}, pr = /* @__PURE__ */ l({ +}, zr = /* @__PURE__ */ l({ __name: "ProjectDetailPage", props: { id: {}, @@ -1512,7 +1608,7 @@ var nr = { router: {} }, setup(t) { - let l = t, u = Ce.project, d = V(), p = y(null), m = y(!0), g = y(!1), v = y(!1), w = n(() => Number(l.id)), T = n(() => [ + let l = t, u = on.project, d = B(), p = l.router, m = y(null), g = y(!0), v = y(!1), w = y(!1), T = n(() => Number(l.id)), O = n(() => [ { id: "overview", label: d("tasks_projects.project.tabs.overview"), @@ -1533,71 +1629,80 @@ var nr = { label: d("tasks_projects.project.tabs.members"), name: `${u}.members` } - ]), O = n(() => String(l.router.currentRoute.value.name ?? "")), k = n(() => p.value?.name ?? d("tasks_projects.projects.title")), A = n(() => ({ - path: Se.board, - query: { project: String(w.value) } - })), j = n(() => Zn(p.value?.customer_id ?? null)); - E(w, () => { - N(); - }), E(O, (e) => M(e)), h(() => { - M(O.value), N(); + ]), k = n(() => String(l.router.currentRoute.value.name ?? "")), A = n(() => m.value?.name ?? d("tasks_projects.projects.title")), j = n(() => ({ + path: W.board, + query: { project: String(T.value) } + })), N = n(() => $t(m.value?.customer_id ?? null)), P = n(() => M.busy), F = n(() => M.allowed && m.value !== null && m.value.customer_id !== null && (m.value.totals?.unbilled_amount ?? 0) > 0); + E(T, () => { + L(); + }), E(k, (e) => I(e)), h(() => { + I(k.value), L(); }); - function M(e) { + function I(e) { e === u && l.router.replace({ name: `${u}.overview`, params: { id: l.id } }); } - async function N() { - m.value = !0; + async function L() { + g.value = !0; try { - p.value = await Ln(l.client, w.value), typeof p.value?.customer_id == "number" && await Qn(l.client); + m.value = await _r(l.client, T.value), typeof m.value?.customer_id == "number" && await en(l.client); } catch (e) { - l.notify("error", z(e, d("tasks_projects.project.load_failed"))); + l.notify("error", H(e, d("tasks_projects.project.load_failed"))); } finally { - m.value = !1; + g.value = !1; } } - function P(e) { + function R(e) { return { name: e.name, params: { id: l.id } }; } - function F(e) { - return O.value === e.name; + function z(e) { + return k.value === e.name; } - function I(e) { - v.value = !1, l.notify("success", d("tasks_projects.projects.updated", { name: e.name })), N(); + function ee(e) { + w.value = !1, l.notify("success", d("tasks_projects.projects.updated", { name: e.name })), L(); } - async function L() { - let e = p.value; - if (!(e === null || g.value)) { - g.value = !0; + async function te() { + let e = m.value; + e !== null && F.value && !P.value && (await bt({ + client: l.client, + router: p, + notify: l.notify, + t: d + }, { projectId: e.id }) || await L()); + } + async function ne() { + let e = m.value; + if (!(e === null || v.value)) { + v.value = !0; try { - e.status === "ARCHIVED" ? (await bn(l.client, e.id), l.notify("success", d("tasks_projects.projects.unarchived", { name: e.name }))) : (await yn(l.client, e.id), l.notify("success", d("tasks_projects.projects.archived", { name: e.name }))), await N(); + e.status === "ARCHIVED" ? (await Kt(l.client, e.id), l.notify("success", d("tasks_projects.projects.unarchived", { name: e.name }))) : (await Gt(l.client, e.id), l.notify("success", d("tasks_projects.projects.archived", { name: e.name }))), await L(); } catch (e) { - l.notify("error", z(e, d("tasks_projects.projects.save_failed"))); + l.notify("error", H(e, d("tasks_projects.projects.save_failed"))); } finally { - g.value = !1; + v.value = !1; } } } - function ee(e) { + function re(e) { return e === "ACTIVE" ? "bg-primary-50! text-primary-500!" : "bg-surface-tertiary! text-muted!"; } - function R(e) { + function ie(e) { return d(e === "ACTIVE" ? "tasks_projects.projects.status.active" : "tasks_projects.projects.status.archived"); } return (n, l) => { - let u = x("BaseBreadcrumbItem"), h = x("BaseBreadcrumb"), y = x("BaseBadge"), w = x("BaseIcon"), E = x("BaseButton"), O = x("router-link"), M = x("BasePageHeader"), te = x("BaseSpinner"), ne = x("router-view"), re = x("BasePage"); - return _(), r(re, null, { + let u = x("BaseBreadcrumbItem"), p = x("BaseBreadcrumb"), h = x("BaseBadge"), y = x("BaseIcon"), T = x("BaseButton"), E = x("router-link"), k = x("BasePageHeader"), M = x("BaseSpinner"), I = x("router-view"), B = x("BasePage"); + return _(), r(B, null, { default: D(() => [ - c(M, { title: k.value }, { - actions: D(() => [o("div", lr, [ - c(O, { to: A.value }, { - default: D(() => [c(E, { variant: "white" }, { - left: D((e) => [c(w, { + c(k, { title: A.value }, { + actions: D(() => [o("div", Fr, [ + c(E, { to: j.value }, { + default: D(() => [c(T, { variant: "white" }, { + left: D((e) => [c(y, { name: "ViewColumnsIcon", class: f(e.class) }, null, 8, ["class"])]), @@ -1606,22 +1711,37 @@ var nr = { })]), _: 1 }, 8, ["to"]), - p.value ? (_(), r(E, { + F.value ? (_(), r(T, { key: 0, variant: "primary-outline", - loading: g.value, - disabled: g.value, - onClick: L + loading: P.value, + disabled: P.value, + onClick: te }, { - default: D(() => [s(S(p.value.status === "ARCHIVED" ? C(d)("tasks_projects.projects.unarchive") : C(d)("tasks_projects.projects.archive")), 1)]), + left: D((e) => [P.value ? i("", !0) : (_(), r(y, { + key: 0, + name: "BanknotesIcon", + class: f(e.class) + }, null, 8, ["class"]))]), + default: D(() => [s(" " + S(C(d)("tasks_projects.project.invoice_project")), 1)]), _: 1 }, 8, ["loading", "disabled"])) : i("", !0), - p.value ? (_(), r(E, { + m.value ? (_(), r(T, { key: 1, + variant: "primary-outline", + loading: v.value, + disabled: v.value, + onClick: ne + }, { + default: D(() => [s(S(m.value.status === "ARCHIVED" ? C(d)("tasks_projects.projects.unarchive") : C(d)("tasks_projects.projects.archive")), 1)]), + _: 1 + }, 8, ["loading", "disabled"])) : i("", !0), + m.value ? (_(), r(T, { + key: 2, variant: "primary", - onClick: l[0] ||= (e) => v.value = !0 + onClick: l[0] ||= (e) => w.value = !0 }, { - left: D((e) => [c(w, { + left: D((e) => [c(y, { name: "PencilIcon", class: f(e.class) }, null, 8, ["class"])]), @@ -1629,7 +1749,7 @@ var nr = { _: 1 })) : i("", !0) ])]), - default: D(() => [c(h, null, { + default: D(() => [c(p, null, { default: D(() => [ c(u, { title: C(d)("tasks_projects.general.home"), @@ -1637,51 +1757,55 @@ var nr = { }, null, 8, ["title"]), c(u, { title: C(d)("tasks_projects.projects.title"), - to: C(Se).projects + to: C(W).projects }, null, 8, ["title", "to"]), c(u, { - title: k.value, + title: A.value, to: "#", active: "" }, null, 8, ["title"]) ]), _: 1 - }), p.value ? (_(), a("div", nr, [ - c(y, { class: f(["rounded-full", ee(p.value.status)]) }, { - default: D(() => [s(S(R(p.value.status)), 1)]), + }), m.value ? (_(), a("div", Or, [ + c(h, { class: f(["rounded-full", re(m.value.status)]) }, { + default: D(() => [s(S(ie(m.value.status)), 1)]), _: 1 }, 8, ["class"]), - p.value.identifier ? (_(), a("span", rr, S(p.value.identifier), 1)) : i("", !0), - p.value.customer_id ? (_(), a("span", ir, [s(S(C(d)("tasks_projects.project.customer")) + ": ", 1), o("span", ar, S(j.value), 1)])) : (_(), a("span", or, S(C(d)("tasks_projects.projects.internal")), 1)), - p.value.due_date ? (_(), a("span", sr, [s(S(C(d)("tasks_projects.project.due_date")) + ": ", 1), o("span", cr, S(C(ge)(p.value.due_date)), 1)])) : i("", !0) + m.value.identifier ? (_(), a("span", kr, S(m.value.identifier), 1)) : i("", !0), + m.value.customer_id ? (_(), a("span", Ar, [s(S(C(d)("tasks_projects.project.customer")) + ": ", 1), o("span", jr, S(N.value), 1)])) : (_(), a("span", Mr, S(C(d)("tasks_projects.projects.internal")), 1)), + m.value.due_date ? (_(), a("span", Nr, [s(S(C(d)("tasks_projects.project.due_date")) + ": ", 1), o("span", Pr, S(C(ut)(m.value.due_date)), 1)])) : i("", !0) ])) : i("", !0)]), _: 1 }, 8, ["title"]), - o("nav", ur, [(_(!0), a(e, null, b(T.value, (e) => (_(), r(O, { + c(Lt, { + client: t.client, + notify: t.notify + }, null, 8, ["client", "notify"]), + o("nav", Ir, [(_(!0), a(e, null, b(O.value, (e) => (_(), r(E, { key: e.id, - to: P(e), + to: R(e), custom: "" }, { default: D(({ href: t, navigate: n }) => [o("a", { href: t, - "aria-current": F(e) ? "page" : void 0, - class: f(["relative -mb-px flex items-center border-b-2 px-5 py-2.5 text-sm leading-5 font-medium whitespace-nowrap transition-colors focus:outline-hidden", F(e) ? "border-primary-400 text-heading" : "border-transparent text-muted hover:border-line-strong hover:text-body"]), + "aria-current": z(e) ? "page" : void 0, + class: f(["relative -mb-px flex items-center border-b-2 px-5 py-2.5 text-sm leading-5 font-medium whitespace-nowrap transition-colors focus:outline-hidden", z(e) ? "border-primary-400 text-heading" : "border-transparent text-muted hover:border-line-strong hover:text-body"]), onClick: n - }, S(e.label), 11, dr)]), + }, S(e.label), 11, Lr)]), _: 2 }, 1032, ["to"]))), 128))]), - m.value && p.value === null ? (_(), a("div", fr, [c(te, { class: "h-8 w-8 text-primary-500" })])) : (_(), r(ne, { + g.value && m.value === null ? (_(), a("div", Rr, [c(M, { class: "h-8 w-8 text-primary-500" })])) : (_(), r(I, { key: 1, - project: p.value, - onRefresh: N + project: m.value, + onRefresh: L }, null, 8, ["project"])), - c(qn, { - show: v.value, + c(Dr, { + show: w.value, client: t.client, notify: t.notify, - project: p.value, - onClose: l[1] ||= (e) => v.value = !1, - onSaved: I + project: m.value, + onClose: l[1] ||= (e) => w.value = !1, + onSaved: ee }, null, 8, [ "show", "client", @@ -1693,19 +1817,19 @@ var nr = { }); }; } -}), mr = { class: "flex items-center justify-end space-x-5" }, hr = { class: "relative table-container" }, gr = { class: "flex items-center" }, _r = { +}), Br = { class: "flex items-center justify-end space-x-5" }, Vr = { class: "relative table-container" }, Hr = { class: "flex items-center" }, Ur = { key: 0, class: "block text-xs font-normal text-muted" -}, vr = { key: 0 }, yr = { +}, Wr = { key: 0 }, Gr = { key: 1, class: "text-subtle" -}, br = { +}, Kr = { key: 1, class: "text-subtle" -}, xr = { key: 0 }, Sr = { +}, qr = { key: 0 }, Jr = { key: 1, class: "text-subtle" -}, Cr = 10, wr = 350, Tr = /* @__PURE__ */ l({ +}, Yr = 10, Xr = 350, Zr = /* @__PURE__ */ l({ __name: "ProjectsIndexPage", props: { client: { type: [Function, Object] }, @@ -1718,7 +1842,7 @@ var nr = { status: "status", default_rate: "default_rate", due_date: "due_date" - }, u = V(), d = y(null), h = y(!1), g = y(!0), b = y(0), w = y(!1), k = y(null), A = y(null), j = v({ + }, u = B(), d = y(null), h = y(!1), g = y(!0), b = y(0), w = y(!1), k = y(null), A = y(null), j = v({ search: "", status: "ACTIVE" }), M = n(() => [ @@ -1779,18 +1903,18 @@ var nr = { } ]), F = n(() => j.search.trim() !== "" || j.status !== "ACTIVE"), I = n(() => !g.value && b.value === 0 && !F.value), L; E(() => j.search, () => { - clearTimeout(L), L = setTimeout(() => R(), wr); - }), E(() => j.status, () => R()), m(() => clearTimeout(L)); - async function ee({ page: e, sort: n }) { + clearTimeout(L), L = setTimeout(() => z(), Xr); + }), E(() => j.status, () => z()), m(() => clearTimeout(L)); + async function R({ page: e, sort: n }) { let r = { page: e, - limit: Cr, - ...hn(n, l) + limit: Yr, + ...Vt(n, l) }; j.status !== "ALL" && (r.status = j.status), j.search.trim() !== "" && (r.search = j.search.trim()), g.value = !0; try { - let e = await gn(t.client, r); - return b.value = e.meta.total, e.data.some((e) => e.customer_id !== null) && Qn(t.client), { + let e = await Ht(t.client, r); + return b.value = e.meta.total, e.data.some((e) => e.customer_id !== null) && en(t.client), { data: e.data, pagination: { totalPages: e.meta.last_page, @@ -1800,73 +1924,73 @@ var nr = { } }; } catch (e) { - return t.notify("error", z(e, u("tasks_projects.projects.load_failed"))), { + return t.notify("error", H(e, u("tasks_projects.projects.load_failed"))), { data: [], pagination: { totalPages: 1, currentPage: 1, totalCount: 0, - limit: Cr + limit: Yr } }; } finally { g.value = !1; } } - function R(e = !1) { + function z(e = !1) { d.value?.refresh(e); } - function te() { - h.value && ne(), h.value = !h.value; + function ee() { + h.value && te(), h.value = !h.value; } - function ne() { + function te() { j.search = "", j.status = "ACTIVE"; } - function re() { + function ne() { k.value = null, w.value = !0; } - function ie(e) { + function re(e) { k.value = e, w.value = !0; } - function ae(e) { + function ie(e) { let n = k.value ? u("tasks_projects.projects.updated", { name: e.name }) : u("tasks_projects.projects.created", { name: e.name }); - w.value = !1, k.value = null, t.notify("success", n), R(); + w.value = !1, k.value = null, t.notify("success", n), z(); } - async function oe(e) { + async function ae(e) { A.value = e.id; try { - e.status === "ARCHIVED" ? (await bn(t.client, e.id), t.notify("success", u("tasks_projects.projects.unarchived", { name: e.name }))) : (await yn(t.client, e.id), t.notify("success", u("tasks_projects.projects.archived", { name: e.name }))), R(!0); + e.status === "ARCHIVED" ? (await Kt(t.client, e.id), t.notify("success", u("tasks_projects.projects.unarchived", { name: e.name }))) : (await Gt(t.client, e.id), t.notify("success", u("tasks_projects.projects.archived", { name: e.name }))), z(!0); } catch (e) { - t.notify("error", z(e, u("tasks_projects.projects.save_failed"))); + t.notify("error", H(e, u("tasks_projects.projects.save_failed"))); } finally { A.value = null; } } - async function se(e) { + async function oe(e) { if (window.confirm(u("tasks_projects.projects.delete_confirm", { name: e.name }))) { A.value = e.id; try { - await xn(t.client, e.id), t.notify("success", u("tasks_projects.projects.deleted", { name: e.name })), R(!0); + await qt(t.client, e.id), t.notify("success", u("tasks_projects.projects.deleted", { name: e.name })), z(!0); } catch (e) { - t.notify("error", z(e, u("tasks_projects.projects.delete_failed"))); + t.notify("error", H(e, u("tasks_projects.projects.delete_failed"))); } finally { A.value = null; } } } - function ce(e) { + function se(e) { return e === "ACTIVE" ? "bg-primary-50! text-primary-500!" : "bg-surface-tertiary! text-muted!"; } - function le(e) { + function ce(e) { return u(e === "ACTIVE" ? "tasks_projects.projects.status.active" : "tasks_projects.projects.status.archived"); } return (t, n) => { - let l = x("BaseBreadcrumbItem"), m = x("BaseBreadcrumb"), g = x("BaseIcon"), v = x("BaseButton"), y = x("router-link"), b = x("BasePageHeader"), E = x("BaseInput"), F = x("BaseInputGroup"), L = x("BaseSelectInput"), R = x("BaseFilterWrapper"), z = x("BaseEmptyPlaceholder"), B = x("BaseBadge"), ue = x("BaseFormatMoney"), de = x("BaseDropdownItem"), fe = x("BaseDropdown"), pe = x("BaseTable"), me = x("BasePage"); + let l = x("BaseBreadcrumbItem"), m = x("BaseBreadcrumb"), g = x("BaseIcon"), v = x("BaseButton"), y = x("router-link"), b = x("BasePageHeader"), E = x("BaseInput"), F = x("BaseInputGroup"), L = x("BaseSelectInput"), z = x("BaseFilterWrapper"), B = x("BaseEmptyPlaceholder"), le = x("BaseBadge"), ue = x("BaseFormatMoney"), de = x("BaseDropdownItem"), fe = x("BaseDropdown"), pe = x("BaseTable"), me = x("BasePage"); return _(), r(me, null, { default: D(() => [ c(b, { title: C(u)("tasks_projects.projects.title") }, { - actions: D(() => [o("div", mr, [ - c(y, { to: C(Se).tasks }, { + actions: D(() => [o("div", Br, [ + c(y, { to: C(W).tasks }, { default: D(() => [c(v, { variant: "white" }, { left: D((e) => [c(g, { name: "ClipboardDocumentListIcon", @@ -1877,7 +2001,7 @@ var nr = { })]), _: 1 }, 8, ["to"]), - c(y, { to: C(Se).reports }, { + c(y, { to: C(W).reports }, { default: D(() => [c(v, { variant: "white" }, { left: D((e) => [c(g, { name: "ChartBarIcon", @@ -1888,9 +2012,20 @@ var nr = { })]), _: 1 }, 8, ["to"]), + c(y, { to: C(W).billing }, { + default: D(() => [c(v, { variant: "white" }, { + left: D((e) => [c(g, { + name: "BanknotesIcon", + class: f(e.class) + }, null, 8, ["class"])]), + default: D(() => [s(" " + S(C(u)("tasks_projects.billing.title")), 1)]), + _: 1 + })]), + _: 1 + }, 8, ["to"]), c(v, { variant: "primary-outline", - onClick: te + onClick: ee }, { right: D((e) => [h.value ? (_(), r(g, { key: 1, @@ -1906,7 +2041,7 @@ var nr = { }), c(v, { variant: "primary", - onClick: re + onClick: ne }, { left: D((e) => [c(g, { name: "PlusIcon", @@ -1929,10 +2064,10 @@ var nr = { })]), _: 1 }, 8, ["title"]), - c(R, { + c(z, { show: h.value, class: "mt-3", - onClear: ne + onClear: te }, { default: D(() => [c(F, { label: C(u)("tasks_projects.general.search"), @@ -1961,13 +2096,13 @@ var nr = { }, 8, ["label"])]), _: 1 }, 8, ["show"]), - O(c(z, { + O(c(B, { title: C(u)("tasks_projects.projects.empty_title"), description: C(u)("tasks_projects.projects.empty_description") }, { actions: D(() => [c(v, { variant: "primary", - onClick: re + onClick: ne }, { left: D((e) => [c(g, { name: "PlusIcon", @@ -1982,54 +2117,54 @@ var nr = { })]), _: 1 }, 8, ["title", "description"]), [[T, I.value]]), - O(o("div", hr, [c(pe, { + O(o("div", Vr, [c(pe, { ref_key: "tableRef", ref: d, - data: ee, + data: R, columns: P.value, class: "mt-3" }, { - "cell-name": D(({ row: e }) => [o("div", gr, [o("span", { + "cell-name": D(({ row: e }) => [o("div", Hr, [o("span", { class: f(["mr-3 inline-block h-2.5 w-2.5 shrink-0 rounded-full", e.data.colour ? "" : "bg-line-default"]), style: p(e.data.colour ? { backgroundColor: e.data.colour } : void 0) }, null, 6), o("span", null, [c(y, { class: "hover:text-primary-500", - to: C(Se).project(e.data.id) + to: C(W).project(e.data.id) }, { default: D(() => [s(S(e.data.name), 1)]), _: 2 - }, 1032, ["to"]), e.data.identifier ? (_(), a("span", _r, S(e.data.identifier), 1)) : i("", !0)])])]), - "cell-status": D(({ row: e }) => [c(B, { class: f(["rounded-full", ce(e.data.status)]) }, { - default: D(() => [s(S(le(e.data.status)), 1)]), + }, 1032, ["to"]), e.data.identifier ? (_(), a("span", Ur, S(e.data.identifier), 1)) : i("", !0)])])]), + "cell-status": D(({ row: e }) => [c(le, { class: f(["rounded-full", se(e.data.status)]) }, { + default: D(() => [s(S(ce(e.data.status)), 1)]), _: 2 }, 1032, ["class"])]), - "cell-customer": D(({ row: e }) => [e.data.customer_id ? (_(), a("span", vr, S(C(Zn)(e.data.customer_id)), 1)) : (_(), a("span", yr, S(C(u)("tasks_projects.projects.internal")), 1))]), - "cell-default_rate": D(({ row: e }) => [e.data.default_rate === null ? (_(), a("span", br, "-")) : (_(), r(ue, { + "cell-customer": D(({ row: e }) => [e.data.customer_id ? (_(), a("span", Wr, S(C($t)(e.data.customer_id)), 1)) : (_(), a("span", Gr, S(C(u)("tasks_projects.projects.internal")), 1))]), + "cell-default_rate": D(({ row: e }) => [e.data.default_rate === null ? (_(), a("span", Kr, "-")) : (_(), r(ue, { key: 0, amount: e.data.default_rate }, null, 8, ["amount"]))]), - "cell-due_date": D(({ row: e }) => [e.data.due_date ? (_(), a("span", xr, S(C(ge)(e.data.due_date)), 1)) : (_(), a("span", Sr, "-"))]), + "cell-due_date": D(({ row: e }) => [e.data.due_date ? (_(), a("span", qr, S(C(ut)(e.data.due_date)), 1)) : (_(), a("span", Jr, "-"))]), "cell-actions": D(({ row: e }) => [c(fe, { "content-loading": A.value === e.data.id }, { activator: D(() => [c(g, { name: "EllipsisHorizontalIcon", class: "h-5 text-muted" })]), default: D(() => [ - c(de, { onClick: (t) => ie(e.data) }, { + c(de, { onClick: (t) => re(e.data) }, { default: D(() => [c(g, { name: "PencilIcon", class: "mr-3 h-5 w-5 text-subtle group-hover:text-muted" }), s(" " + S(C(u)("tasks_projects.general.edit")), 1)]), _: 1 }, 8, ["onClick"]), - c(de, { onClick: (t) => oe(e.data) }, { + c(de, { onClick: (t) => ae(e.data) }, { default: D(() => [c(g, { name: e.data.status === "ARCHIVED" ? "ArrowPathIcon" : "ArchiveBoxIcon", class: "mr-3 h-5 w-5 text-subtle group-hover:text-muted" }, null, 8, ["name"]), s(" " + S(e.data.status === "ARCHIVED" ? C(u)("tasks_projects.projects.unarchive") : C(u)("tasks_projects.projects.archive")), 1)]), _: 2 }, 1032, ["onClick"]), - c(de, { onClick: (t) => se(e.data) }, { + c(de, { onClick: (t) => oe(e.data) }, { default: D(() => [c(g, { name: "TrashIcon", class: "mr-3 h-5 w-5 text-subtle group-hover:text-muted" @@ -2041,13 +2176,13 @@ var nr = { }, 1032, ["content-loading"])]), _: 1 }, 8, ["columns"])], 512), [[T, !I.value]]), - c(qn, { + c(Dr, { show: w.value, client: e.client, notify: e.notify, project: k.value, onClose: n[2] ||= (e) => w.value = !1, - onSaved: ae + onSaved: ie }, null, 8, [ "show", "client", @@ -2059,22 +2194,22 @@ var nr = { }); }; } -}), Er = { class: "py-4" }, Dr = { class: "rounded-xl border border-line-default bg-surface p-5" }, Or = { class: "flex flex-col gap-4 lg:flex-row lg:items-end" }, kr = { +}), Qr = { class: "py-4" }, $r = { class: "rounded-xl border border-line-default bg-surface p-5" }, ei = { class: "flex flex-col gap-4 lg:flex-row lg:items-end" }, ti = { key: 0, class: "mt-3 text-xs text-subtle" -}, Ar = { class: "mt-4 overflow-hidden rounded-xl border border-line-default bg-surface" }, jr = { +}, ni = { class: "mt-4 overflow-hidden rounded-xl border border-line-default bg-surface" }, ri = { key: 0, class: "flex justify-center py-10" -}, Mr = { +}, ii = { key: 1, class: "px-5 py-8 text-center text-sm text-muted" -}, Nr = { +}, ai = { key: 2, class: "divide-y divide-line-light" -}, Pr = { class: "text-sm font-medium text-heading" }, Fr = { class: "text-xs text-muted" }, Ir = { +}, oi = { class: "text-sm font-medium text-heading" }, si = { class: "text-xs text-muted" }, ci = { key: 1, class: "text-subtle" -}, Lr = /* @__PURE__ */ l({ +}, li = /* @__PURE__ */ l({ __name: "ProjectMembersTab", props: { id: {}, @@ -2083,7 +2218,7 @@ var nr = { project: {} }, setup(t) { - let l = t, u = V(), d = y([]), p = y([]), m = y(!0), g = y(!1), v = y(null), w = y(null), T = y(""), E = y({}), O = n(() => l.project?.id ?? Number(l.id)), k = n(() => p.value.filter((e) => !d.value.some((t) => t.user_id === e.id)).map((e) => ({ + let l = t, u = B(), d = y([]), p = y([]), m = y(!0), g = y(!1), v = y(null), w = y(null), T = y(""), E = y({}), O = n(() => l.project?.id ?? Number(l.id)), k = n(() => p.value.filter((e) => !d.value.some((t) => t.user_id === e.id)).map((e) => ({ id: e.id, label: e.name }))); @@ -2093,14 +2228,14 @@ var nr = { async function A() { m.value = !0; try { - p.value = await Sn(l.client); + p.value = await Jt(l.client); } catch (e) { - l.notify("error", z(e, u("tasks_projects.tasks.members_failed"))); + l.notify("error", H(e, u("tasks_projects.tasks.members_failed"))); } try { - d.value = await Rn(l.client, O.value); + d.value = await vr(l.client, O.value); } catch (e) { - l.notify("error", z(e, u("tasks_projects.project.members.load_failed"))); + l.notify("error", H(e, u("tasks_projects.project.members.load_failed"))); } finally { m.value = !1; } @@ -2113,12 +2248,12 @@ var nr = { if (!(e === null || g.value)) { g.value = !0, E.value = {}; try { - await zn(l.client, O.value, { + await yr(l.client, O.value, { user_id: e.id, - rate: pe(T.value) + rate: st(T.value) }), l.notify("success", u("tasks_projects.project.members.attached", { name: e.label })), w.value = null, T.value = "", await A(); } catch (e) { - E.value = ce(e), l.notify("error", z(e, u("tasks_projects.project.members.attach_failed"))); + E.value = at(e), l.notify("error", H(e, u("tasks_projects.project.members.attach_failed"))); } finally { g.value = !1; } @@ -2129,9 +2264,9 @@ var nr = { if (window.confirm(u("tasks_projects.project.members.detach_confirm", { name: t }))) { v.value = e.user_id; try { - await Bn(l.client, O.value, e.user_id), l.notify("success", u("tasks_projects.project.members.detached", { name: t })), await A(); + await br(l.client, O.value, e.user_id), l.notify("success", u("tasks_projects.project.members.detached", { name: t })), await A(); } catch (e) { - l.notify("error", z(e, u("tasks_projects.project.members.detach_failed"))); + l.notify("error", H(e, u("tasks_projects.project.members.detach_failed"))); } finally { v.value = null; } @@ -2139,7 +2274,7 @@ var nr = { } return (t, n) => { let l = x("BaseSelectInput"), p = x("BaseInputGroup"), h = x("BaseInput"), y = x("BaseIcon"), O = x("BaseButton"), A = x("BaseSpinner"), P = x("BaseFormatMoney"); - return _(), a("div", Er, [o("div", Dr, [o("div", Or, [ + return _(), a("div", Qr, [o("div", $r, [o("div", ei, [ c(p, { label: C(u)("tasks_projects.project.members.member"), error: E.value.user_id, @@ -2191,10 +2326,10 @@ var nr = { default: D(() => [s(" " + S(C(u)("tasks_projects.project.members.attach")), 1)]), _: 1 }, 8, ["loading", "disabled"]) - ]), k.value.length === 0 && !m.value ? (_(), a("p", kr, S(C(u)("tasks_projects.project.members.all_attached")), 1)) : i("", !0)]), o("div", Ar, [m.value ? (_(), a("div", jr, [c(A, { class: "h-6 w-6 text-primary-500" })])) : d.value.length === 0 ? (_(), a("p", Mr, S(C(u)("tasks_projects.project.members.empty")), 1)) : (_(), a("ul", Nr, [(_(!0), a(e, null, b(d.value, (e) => (_(), a("li", { + ]), k.value.length === 0 && !m.value ? (_(), a("p", ti, S(C(u)("tasks_projects.project.members.all_attached")), 1)) : i("", !0)]), o("div", ni, [m.value ? (_(), a("div", ri, [c(A, { class: "h-6 w-6 text-primary-500" })])) : d.value.length === 0 ? (_(), a("p", ii, S(C(u)("tasks_projects.project.members.empty")), 1)) : (_(), a("ul", ai, [(_(!0), a(e, null, b(d.value, (e) => (_(), a("li", { key: e.id, class: "flex items-center justify-between px-5 py-4" - }, [o("div", null, [o("p", Pr, S(j(e.user_id)), 1), o("p", Fr, [s(S(C(u)("tasks_projects.project.members.rate")) + ": ", 1), e.rate === null ? (_(), a("span", Ir, S(C(u)("tasks_projects.tasks.none")), 1)) : (_(), r(P, { + }, [o("div", null, [o("p", oi, S(j(e.user_id)), 1), o("p", si, [s(S(C(u)("tasks_projects.project.members.rate")) + ": ", 1), e.rate === null ? (_(), a("span", ci, S(C(u)("tasks_projects.tasks.none")), 1)) : (_(), r(P, { key: 0, amount: e.rate }, null, 8, ["amount"]))])]), c(O, { @@ -2213,104 +2348,120 @@ var nr = { ])]))), 128))]))])]); }; } -}), Rr = { +}), ui = { key: 0, class: "py-6" -}, zr = { class: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4" }, Br = { class: "rounded-xl border border-line-default bg-surface p-5" }, Vr = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Hr = { class: "mt-2 text-2xl font-semibold text-heading" }, Ur = { class: "mt-1 text-xs text-muted" }, Wr = { class: "rounded-xl border border-line-default bg-surface p-5" }, Gr = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Kr = { class: "mt-2 text-2xl font-semibold text-heading" }, qr = { class: "mt-1 text-xs text-muted" }, Jr = { class: "rounded-xl border border-line-default bg-surface p-5" }, Yr = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Xr = { class: "mt-2 text-2xl font-semibold text-heading" }, Zr = { class: "rounded-xl border border-line-default bg-surface p-5" }, Qr = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, $r = { class: "mt-2 text-2xl font-semibold text-heading" }, ei = ["title"], ti = { class: "mt-4 rounded-xl border border-line-default bg-surface p-5" }, ni = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, ri = { class: "mt-2 text-sm text-body" }, ii = { class: "mt-3 h-2 w-full overflow-hidden rounded-full bg-surface-tertiary" }, ai = { +}, di = { class: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4" }, fi = { class: "rounded-xl border border-line-default bg-surface p-5" }, pi = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, mi = { class: "mt-2 text-2xl font-semibold text-heading" }, hi = { class: "mt-1 text-xs text-muted" }, gi = { class: "rounded-xl border border-line-default bg-surface p-5" }, _i = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, vi = { class: "mt-2 text-2xl font-semibold text-heading" }, yi = { class: "mt-1 text-xs text-muted" }, bi = { class: "rounded-xl border border-line-default bg-surface p-5" }, xi = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Si = { class: "mt-2 text-2xl font-semibold text-heading" }, Ci = { class: "rounded-xl border border-line-default bg-surface p-5" }, wi = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Ti = { class: "mt-2 text-2xl font-semibold text-heading" }, Ei = { class: "mt-4 rounded-xl border border-line-default bg-surface p-5" }, Di = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Oi = { class: "mt-2 text-sm text-body" }, ki = { class: "mt-3 h-2 w-full overflow-hidden rounded-full bg-surface-tertiary" }, Ai = { key: 0, class: "mt-2 text-xs font-medium text-status-red" -}, oi = { +}, ji = { key: 1, class: "mt-2 text-sm text-subtle" -}, si = { class: "mt-4 rounded-xl border border-line-default bg-surface p-5" }, ci = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, li = { +}, Mi = { class: "mt-4 rounded-xl border border-line-default bg-surface p-5" }, Ni = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Pi = { key: 0, class: "mt-2 text-sm whitespace-pre-line text-body" -}, ui = { +}, Fi = { key: 1, class: "mt-2 text-sm text-subtle" -}, di = { +}, Ii = { key: 1, class: "flex justify-center py-16" -}, fi = /* @__PURE__ */ l({ +}, Li = /* @__PURE__ */ l({ __name: "ProjectOverviewTab", - props: { project: {} }, - setup(t) { - let r = t, l = V(), u = n(() => r.project?.totals ?? null), d = n(() => r.project?.budget_minutes ?? null), m = n(() => { - let e = d.value, t = u.value?.logged_minutes ?? 0; + props: { + client: { type: [Function, Object] }, + notify: { type: Function }, + router: {}, + project: {} + }, + emits: ["refresh"], + setup(t, { emit: l }) { + let u = t, d = l, m = B(), h = n(() => u.project?.totals ?? null), g = n(() => u.project?.budget_minutes ?? null), v = n(() => { + let e = g.value, t = h.value?.logged_minutes ?? 0; return e ? Math.min(100, Math.round(t / e * 100)) : 0; - }), h = n(() => r.project?.customer_id !== null && (u.value?.unbilled_amount ?? 0) > 0), g = n(() => { - let e = d.value, t = u.value?.logged_minutes ?? 0; + }), y = n(() => M.allowed && u.project?.customer_id !== null && (h.value?.unbilled_amount ?? 0) > 0), b = n(() => M.busy), w = n(() => { + let e = g.value, t = h.value?.logged_minutes ?? 0; return e && t > e ? t - e : 0; }); - return (n, r) => { - let v = x("BaseFormatMoney"), y = x("BaseIcon"), b = x("BaseButton"), w = x("BaseSpinner"); - return t.project && u.value ? (_(), a("div", Rr, [ - o("div", zr, [ - o("div", Br, [ - o("p", Vr, S(C(l)("tasks_projects.project.overview.tasks")), 1), - o("p", Hr, S(u.value.tasks.total), 1), - o("p", Ur, S(C(l)("tasks_projects.project.overview.open_tasks", { count: u.value.tasks.open })) + " · " + S(C(l)("tasks_projects.project.overview.closed_tasks", { count: u.value.tasks.closed })), 1) + async function T() { + let e = u.project; + e !== null && y.value && !b.value && (await bt({ + client: u.client, + router: u.router, + notify: u.notify, + t: m + }, { projectId: e.id }) || d("refresh")); + } + return (n, l) => { + let u = x("BaseFormatMoney"), d = x("BaseIcon"), E = x("BaseButton"), O = x("BaseSpinner"); + return t.project && h.value ? (_(), a("div", ui, [ + o("div", di, [ + o("div", fi, [ + o("p", pi, S(C(m)("tasks_projects.project.overview.tasks")), 1), + o("p", mi, S(h.value.tasks.total), 1), + o("p", hi, S(C(m)("tasks_projects.project.overview.open_tasks", { count: h.value.tasks.open })) + " · " + S(C(m)("tasks_projects.project.overview.closed_tasks", { count: h.value.tasks.closed })), 1) ]), - o("div", Wr, [ - o("p", Gr, S(C(l)("tasks_projects.project.overview.logged")), 1), - o("p", Kr, S(C(ve)(u.value.logged_minutes)), 1), - o("p", qr, S(C(l)("tasks_projects.project.overview.billable")) + ": " + S(C(ve)(u.value.billable_minutes)), 1) + o("div", gi, [ + o("p", _i, S(C(m)("tasks_projects.project.overview.logged")), 1), + o("p", vi, S(C(ft)(h.value.logged_minutes)), 1), + o("p", yi, S(C(m)("tasks_projects.project.overview.billable")) + ": " + S(C(ft)(h.value.billable_minutes)), 1) ]), - o("div", Jr, [o("p", Yr, S(C(l)("tasks_projects.project.overview.billable_amount")), 1), o("p", Xr, [c(v, { amount: u.value.billable_amount }, null, 8, ["amount"])])]), - o("div", Zr, [ - o("p", Qr, S(C(l)("tasks_projects.project.overview.unbilled_amount")), 1), - o("p", $r, [c(v, { amount: u.value.unbilled_amount }, null, 8, ["amount"])]), - h.value ? (_(), a("span", { + o("div", bi, [o("p", xi, S(C(m)("tasks_projects.project.overview.billable_amount")), 1), o("p", Si, [c(u, { amount: h.value.billable_amount }, null, 8, ["amount"])])]), + o("div", Ci, [ + o("p", wi, S(C(m)("tasks_projects.project.overview.unbilled_amount")), 1), + o("p", Ti, [c(u, { amount: h.value.unbilled_amount }, null, 8, ["amount"])]), + y.value ? (_(), r(E, { key: 0, - class: "mt-2 inline-flex", - title: C(l)("tasks_projects.project.invoice_soon") - }, [c(b, { + class: "mt-2", variant: "primary-outline", size: "sm", - disabled: "" + loading: b.value, + disabled: b.value, + onClick: T }, { - left: D((e) => [c(y, { + left: D((e) => [b.value ? i("", !0) : (_(), r(d, { + key: 0, name: "BanknotesIcon", class: f(e.class) - }, null, 8, ["class"])]), - default: D(() => [s(" " + S(C(l)("tasks_projects.project.invoice_project")), 1)]), + }, null, 8, ["class"]))]), + default: D(() => [s(" " + S(C(m)("tasks_projects.project.invoice_project")), 1)]), _: 1 - })], 8, ei)) : i("", !0) + }, 8, ["loading", "disabled"])) : i("", !0) ]) ]), - o("div", ti, [o("p", ni, S(C(l)("tasks_projects.project.overview.budget")), 1), d.value ? (_(), a(e, { key: 0 }, [ - o("p", ri, S(C(l)("tasks_projects.project.overview.budget_used", { - used: C(ve)(u.value.logged_minutes), - total: C(ve)(d.value) + o("div", Ei, [o("p", Di, S(C(m)("tasks_projects.project.overview.budget")), 1), g.value ? (_(), a(e, { key: 0 }, [ + o("p", Oi, S(C(m)("tasks_projects.project.overview.budget_used", { + used: C(ft)(h.value.logged_minutes), + total: C(ft)(g.value) })), 1), - o("div", ii, [o("div", { - class: f(["h-2 rounded-full", g.value > 0 ? "bg-status-red" : "bg-primary-500"]), - style: p({ width: `${m.value}%` }) + o("div", ki, [o("div", { + class: f(["h-2 rounded-full", w.value > 0 ? "bg-status-red" : "bg-primary-500"]), + style: p({ width: `${v.value}%` }) }, null, 6)]), - g.value > 0 ? (_(), a("p", ai, S(C(l)("tasks_projects.project.overview.budget_over", { amount: C(ve)(g.value) })), 1)) : i("", !0) - ], 64)) : (_(), a("p", oi, S(C(l)("tasks_projects.project.overview.no_budget")), 1))]), - o("div", si, [o("p", ci, S(C(l)("tasks_projects.project.overview.description")), 1), t.project.description ? (_(), a("p", li, S(t.project.description), 1)) : (_(), a("p", ui, S(C(l)("tasks_projects.project.overview.no_description")), 1))]) - ])) : (_(), a("div", di, [c(w, { class: "h-8 w-8 text-primary-500" })])); + w.value > 0 ? (_(), a("p", Ai, S(C(m)("tasks_projects.project.overview.budget_over", { amount: C(ft)(w.value) })), 1)) : i("", !0) + ], 64)) : (_(), a("p", ji, S(C(m)("tasks_projects.project.overview.no_budget")), 1))]), + o("div", Mi, [o("p", Ni, S(C(m)("tasks_projects.project.overview.description")), 1), t.project.description ? (_(), a("p", Pi, S(t.project.description), 1)) : (_(), a("p", Fi, S(C(m)("tasks_projects.project.overview.no_description")), 1))]) + ])) : (_(), a("div", Ii, [c(O, { class: "h-8 w-8 text-primary-500" })])); }; } -}), pi = { +}), Ri = { project: "", user: "", status: "", search: "" }; -function mi(e) { +function zi(e) { return e === "uninvoiced" || e === "invoiced"; } -function hi(e) { +function Bi(e) { return { - project: Ci(e.project), - user: Ci(e.user), - status: wi(e.status), - search: Si(e.search).slice(0, 200) + project: Ji(e.project), + user: Ji(e.user), + status: Yi(e.status), + search: qi(e.search).slice(0, 200) }; } -function gi(e) { +function Vi(e) { let t = {}; for (let n of [ "project", @@ -2320,10 +2471,10 @@ function gi(e) { ]) e[n] !== "" && (t[n] = e[n]); return t; } -function _i(e) { +function Hi(e) { return e.project !== "" || e.user !== "" || e.status !== "" || e.search !== ""; } -function vi(e) { +function Ui(e) { return [ e.project, e.user, @@ -2331,42 +2482,42 @@ function vi(e) { e.search ].join("|"); } -function yi(e, t) { +function Wi(e, t) { return e.project === t.project && e.user === t.user && e.status === t.status && e.search === t.search; } -function bi(e, t = {}) { - let n = {}, r = t.projectId ?? xi(e.project); +function Gi(e, t = {}) { + let n = {}, r = t.projectId ?? Ki(e.project); r !== null && (n.project_id = r); - let i = xi(e.user); - if (i !== null && (n.assignee_id = i), mi(e.status)) n.invoiced = +(e.status === "invoiced"); + let i = Ki(e.user); + if (i !== null && (n.assignee_id = i), zi(e.status)) n.invoiced = +(e.status === "invoiced"); else { - let t = xi(e.status); + let t = Ki(e.status); t !== null && (n.task_status_id = t); } return e.search !== "" && (n.search = e.search), n; } -function xi(e) { +function Ki(e) { let t = Number(e); return e !== "" && Number.isInteger(t) && t > 0 ? t : null; } -function Si(e) { +function qi(e) { let t = Array.isArray(e) ? e[0] : e; return typeof t == "string" ? t.trim() : ""; } -function Ci(e) { - let t = Si(e); - return xi(t) === null ? "" : t; +function Ji(e) { + let t = qi(e); + return Ki(t) === null ? "" : t; } -function wi(e) { - let t = Si(e); - return mi(t) ? t : Ci(e); +function Yi(e) { + let t = qi(e); + return zi(t) ? t : Ji(e); } //#endregion //#region resources/js/components/TaskFilters.vue?vue&type=script&setup=true&lang.ts -var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { +var Xi = { class: "mt-4 flex flex-wrap items-end gap-3" }, Zi = { key: 0, class: "min-w-44 flex-1" -}, Di = { class: "mb-1 block text-xs font-medium text-muted" }, Oi = { class: "min-w-44 flex-1" }, ki = { class: "mb-1 block text-xs font-medium text-muted" }, Ai = { class: "min-w-44 flex-1" }, ji = { class: "mb-1 block text-xs font-medium text-muted" }, Mi = { class: "min-w-44 flex-1" }, Ni = { class: "mb-1 block text-xs font-medium text-muted" }, Pi = 350, Fi = /* @__PURE__ */ l({ +}, Qi = { class: "mb-1 block text-xs font-medium text-muted" }, $i = { class: "min-w-44 flex-1" }, ea = { class: "mb-1 block text-xs font-medium text-muted" }, ta = { class: "min-w-44 flex-1" }, na = { class: "mb-1 block text-xs font-medium text-muted" }, ra = { class: "min-w-44 flex-1" }, ia = { class: "mb-1 block text-xs font-medium text-muted" }, aa = 350, oa = /* @__PURE__ */ l({ __name: "TaskFilters", props: { modelValue: {}, @@ -2380,7 +2531,7 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { }, emits: ["update:modelValue"], setup(e, { emit: t }) { - let r = e, s = t, l = V(), u = y(r.modelValue.search), d, f = n(() => [{ + let r = e, s = t, l = B(), u = y(r.modelValue.search), d, f = n(() => [{ id: "", label: l("tasks_projects.tasks.filters.all_projects") }, ...r.projects.map((e) => ({ @@ -2418,11 +2569,11 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { }), b = n({ get: () => T(h.value, r.modelValue.status), set: (e) => D({ status: e?.id ?? "" }) - }), w = n(() => _i(r.modelValue)); + }), w = n(() => Hi(r.modelValue)); E(() => r.modelValue.search, (e) => { e !== u.value && (u.value = e); }), E(u, (e) => { - clearTimeout(d), d = setTimeout(() => D({ search: e.trim() }), Pi); + clearTimeout(d), d = setTimeout(() => D({ search: e.trim() }), aa); }), m(() => clearTimeout(d)); function T(e, t) { return e.find((e) => e.id === t) ?? e[0]; @@ -2434,30 +2585,30 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { }); } function O() { - u.value = "", s("update:modelValue", { ...pi }); + u.value = "", s("update:modelValue", { ...Ri }); } return (t, n) => { let r = x("BaseSelectInput"), s = x("BaseInput"); - return _(), a("div", Ti, [ - e.lockProject ? i("", !0) : (_(), a("label", Ei, [o("span", Di, S(C(l)("tasks_projects.tasks.filters.project")), 1), c(r, { + return _(), a("div", Xi, [ + e.lockProject ? i("", !0) : (_(), a("label", Zi, [o("span", Qi, S(C(l)("tasks_projects.tasks.filters.project")), 1), c(r, { modelValue: g.value, "onUpdate:modelValue": n[0] ||= (e) => g.value = e, options: f.value, "label-key": "label" }, null, 8, ["modelValue", "options"])])), - o("label", Oi, [o("span", ki, S(C(l)("tasks_projects.tasks.filters.member")), 1), c(r, { + o("label", $i, [o("span", ea, S(C(l)("tasks_projects.tasks.filters.member")), 1), c(r, { modelValue: v.value, "onUpdate:modelValue": n[1] ||= (e) => v.value = e, options: p.value, "label-key": "label" }, null, 8, ["modelValue", "options"])]), - o("label", Ai, [o("span", ji, S(C(l)("tasks_projects.tasks.filters.status")), 1), c(r, { + o("label", ta, [o("span", na, S(C(l)("tasks_projects.tasks.filters.status")), 1), c(r, { modelValue: b.value, "onUpdate:modelValue": n[2] ||= (e) => b.value = e, options: h.value, "label-key": "label" }, null, 8, ["modelValue", "options"])]), - o("label", Mi, [o("span", Ni, S(C(l)("tasks_projects.tasks.filters.search")), 1), c(s, { + o("label", ra, [o("span", ia, S(C(l)("tasks_projects.tasks.filters.search")), 1), c(s, { modelValue: u.value, "onUpdate:modelValue": n[3] ||= (e) => u.value = e, type: "text", @@ -2474,39 +2625,48 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { ]); }; } -}), Ii = { +}), sa = { key: 0, class: "mt-3 flex flex-wrap items-center gap-3 rounded-lg border border-primary-200 bg-primary-50 px-4 py-2.5" -}, Li = { class: "text-sm font-medium text-primary-700" }, Ri = { class: "min-w-48" }, zi = ["title"], Bi = /* @__PURE__ */ l({ +}, ca = { class: "text-sm font-medium text-primary-700" }, la = { class: "min-w-48" }, ua = /* @__PURE__ */ l({ __name: "BulkActionBar", props: { count: {}, statuses: {}, - busy: { type: Boolean } + busy: { type: Boolean }, + invoicing: { + type: Boolean, + default: !1 + }, + canInvoice: { + type: Boolean, + default: !0 + } }, emits: [ "status", "delete", + "invoice", "clear", "select-page" ], setup(e, { emit: t }) { - let r = e, l = t, u = V(), d = y(null), p = n(() => r.statuses.map((e) => ({ + let l = e, u = t, d = B(), p = y(null), m = n(() => l.statuses.map((e) => ({ id: e.id, label: e.name }))); - return E(d, (e) => { - e !== null && (l("status", e.id), d.value = null); + return E(p, (e) => { + e !== null && (u("status", e.id), p.value = null); }), (t, n) => { - let r = x("BaseSelectInput"), m = x("BaseIcon"), h = x("BaseButton"); - return e.count > 0 ? (_(), a("div", Ii, [ - o("span", Li, S(C(u)("tasks_projects.tasks.bulk.selected", { count: e.count })), 1), - o("div", Ri, [c(r, { - modelValue: d.value, - "onUpdate:modelValue": n[0] ||= (e) => d.value = e, - options: p.value, + let l = x("BaseSelectInput"), h = x("BaseIcon"), g = x("BaseButton"); + return e.count > 0 ? (_(), a("div", sa, [ + o("span", ca, S(C(d)("tasks_projects.tasks.bulk.selected", { count: e.count })), 1), + o("div", la, [c(l, { + modelValue: p.value, + "onUpdate:modelValue": n[0] ||= (e) => p.value = e, + options: m.value, disabled: e.busy, - placeholder: C(u)("tasks_projects.tasks.bulk.change_status"), + placeholder: C(d)("tasks_projects.tasks.bulk.change_status"), "label-key": "label" }, null, 8, [ "modelValue", @@ -2514,52 +2674,53 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { "disabled", "placeholder" ])]), - c(h, { + c(g, { variant: "primary-outline", size: "sm", disabled: e.busy, - onClick: n[1] ||= (e) => l("delete") + onClick: n[1] ||= (e) => u("delete") }, { - left: D((e) => [c(m, { + left: D((e) => [c(h, { name: "TrashIcon", class: f(e.class) }, null, 8, ["class"])]), - default: D(() => [s(" " + S(C(u)("tasks_projects.tasks.bulk.delete")), 1)]), + default: D(() => [s(" " + S(C(d)("tasks_projects.tasks.bulk.delete")), 1)]), _: 1 }, 8, ["disabled"]), - o("span", { - title: C(u)("tasks_projects.tasks.invoice_soon"), - class: "inline-flex" - }, [c(h, { + e.canInvoice ? (_(), r(g, { + key: 0, variant: "primary-outline", size: "sm", - disabled: "" + loading: e.invoicing, + disabled: e.busy || e.invoicing, + onClick: n[2] ||= (e) => u("invoice") }, { - left: D((e) => [c(m, { + left: D((t) => [e.invoicing ? i("", !0) : (_(), r(h, { + key: 0, name: "BanknotesIcon", - class: f(e.class) - }, null, 8, ["class"])]), - default: D(() => [s(" " + S(C(u)("tasks_projects.tasks.bulk.invoice")), 1)]), + class: f(t.class) + }, null, 8, ["class"]))]), + default: D(() => [s(" " + S(C(d)("tasks_projects.tasks.bulk.invoice")), 1)]), _: 1 - })], 8, zi), + }, 8, ["loading", "disabled"])) : i("", !0), o("button", { type: "button", class: "ml-auto text-sm font-medium text-primary-600 hover:underline", - onClick: n[2] ||= (e) => l("select-page") - }, S(C(u)("tasks_projects.tasks.bulk.select_page")), 1), + onClick: n[3] ||= (e) => u("select-page") + }, S(C(d)("tasks_projects.tasks.bulk.select_page")), 1), o("button", { type: "button", class: "text-sm font-medium text-primary-600 hover:underline", - onClick: n[3] ||= (e) => l("clear") - }, S(C(u)("tasks_projects.tasks.bulk.clear")), 1) + onClick: n[4] ||= (e) => u("clear") + }, S(C(d)("tasks_projects.tasks.bulk.clear")), 1) ])) : i("", !0); }; } -}), Vi = /* @__PURE__ */ l({ +}), da = /* @__PURE__ */ l({ __name: "InvoicedBadge", props: { state: { default: "none" } }, setup(e) { - let t = e, a = V(), o = n(() => t.state === "invoiced" || t.state === "uninvoiced"), c = n(() => t.state === "invoiced" ? a("tasks_projects.tasks.invoiced") : a("tasks_projects.tasks.uninvoiced")), l = n(() => t.state === "invoiced" ? "bg-alert-success-bg! text-alert-success-text!" : "bg-alert-warning-bg! text-alert-warning-text!"); + let t = e, a = B(), o = n(() => t.state === "invoiced" || t.state === "uninvoiced"), c = n(() => t.state === "invoiced" ? a("tasks_projects.tasks.invoiced") : a("tasks_projects.tasks.uninvoiced")), l = n(() => t.state === "invoiced" ? "bg-alert-success-bg! text-alert-success-text!" : "bg-alert-warning-bg! text-alert-warning-text!"); return (e, t) => { let n = x("BaseBadge"); return o.value ? (_(), r(n, { @@ -2571,15 +2732,15 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { }, 8, ["class"])) : i("", !0); }; } -}), Hi = [ +}), fa = [ "LOW", "NORMAL", "HIGH", "URGENT" -], Ui = { class: "flex w-full items-center justify-between" }, Wi = { +], pa = { class: "flex w-full items-center justify-between" }, ma = { key: 0, class: "ml-2 text-sm font-normal text-muted" -}, Gi = { class: "space-y-5 px-6 py-6" }, Ki = { class: "flex items-center justify-between border-t border-line-default px-6 py-4" }, qi = { key: 1 }, Ji = { class: "flex space-x-3" }, Yi = /* @__PURE__ */ l({ +}, ha = { class: "space-y-5 px-6 py-6" }, ga = { class: "flex items-center justify-between border-t border-line-default px-6 py-4" }, _a = { key: 1 }, va = { class: "flex space-x-3" }, ya = /* @__PURE__ */ l({ __name: "TaskFormModal", props: { show: { type: Boolean }, @@ -2599,7 +2760,7 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { "deleted" ], setup(e, { emit: t }) { - let l = e, u = t, d = V(), f = v({ + let l = e, u = t, d = B(), f = v({ name: "", description: "", estimateHours: "", @@ -2607,7 +2768,7 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { dueDate: "", billable: !0 }), p = y(null), m = y(null), h = y(null), g = y(null), b = y(null), w = y({}), T = y(!1), O = y(!1), k = y(!1), j = n(() => !l.compact || k.value), M = n({ - get: () => ee(l.projects, m.value), + get: () => R(l.projects, m.value), set: (e) => { m.value = e?.id ?? null; } @@ -2617,29 +2778,29 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { }))), I = n(() => l.members.map((e) => ({ id: e.id, label: e.name - }))), L = n(() => Hi.map((e, t) => ({ + }))), L = n(() => fa.map((e, t) => ({ id: t, label: d(`tasks_projects.tasks.priority.${e.toLowerCase()}`) }))); E(() => l.show, (e) => { - e && R(); + e && z(); }, { immediate: !0 }); - function ee(e, t) { + function R(e, t) { return t === null ? null : e.find((e) => e.id === t) ?? null; } - function R() { + function z() { let e = l.task; - f.name = e?.name ?? "", f.description = e?.description ?? "", f.estimateHours = me(e?.estimated_minutes ?? null), f.rate = fe(e?.rate ?? null), f.dueDate = e?.due_date ?? "", f.billable = e?.billable ?? !0; + f.name = e?.name ?? "", f.description = e?.description ?? "", f.estimateHours = ct(e?.estimated_minutes ?? null), f.rate = ot(e?.rate ?? null), f.dueDate = e?.due_date ?? "", f.billable = e?.billable ?? !0; let t = l.statuses.find((e) => e.is_default) ?? l.statuses[0], n = e?.task_status_id ?? l.defaults?.task_status_id ?? t?.id ?? null; - p.value = ee(F.value, n), m.value = e?.project_id ?? l.defaults?.project_id ?? null, h.value = ee(I.value, e?.assignee_id ?? null), g.value = e?.priority ? L.value[Hi.indexOf(e.priority)] ?? null : null, b.value = e?.customer_id ?? null, w.value = {}, k.value = !1; + p.value = R(F.value, n), m.value = e?.project_id ?? l.defaults?.project_id ?? null, h.value = R(I.value, e?.assignee_id ?? null), g.value = e?.priority ? L.value[fa.indexOf(e.priority)] ?? null : null, b.value = e?.customer_id ?? null, w.value = {}, k.value = !1, b.value !== null && en(l.client); } - function te(e) { - f.dueDate = e ? _e(e) : ""; + function ee(e) { + f.dueDate = e ? dt(e) : ""; } - function ne() { + function te() { let e = p.value?.id ?? null; if (e === null) return null; - let t = g.value === null ? null : Hi[g.value.id]; + let t = g.value === null ? null : fa[g.value.id]; return { name: f.name.trim(), task_status_id: e, @@ -2649,60 +2810,60 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { assignee_id: h.value?.id ?? null, priority: t, due_date: f.dueDate || null, - estimated_minutes: he(f.estimateHours), + estimated_minutes: lt(f.estimateHours), billable: f.billable, - rate: pe(f.rate) + rate: st(f.rate) }; } - async function re() { + async function ne() { if (T.value) return; if (f.name.trim() === "") { w.value = { name: d("tasks_projects.tasks.name_required") }; return; } - let e = ne(); + let e = te(); if (e === null) { l.notify("error", d("tasks_projects.task_statuses.none")); return; } T.value = !0, w.value = {}; try { - let t = l.task, n = t ? await kn(l.client, t.id, e) : await On(l.client, e); + let t = l.task, n = t ? await lr(l.client, t.id, e) : await cr(l.client, e); u("saved", n); } catch (e) { - w.value = ce(e), l.notify("error", z(e, ie(e, "save_failed"))); + w.value = at(e), l.notify("error", H(e, re(e, "save_failed"))); } finally { T.value = !1; } } - function ie(e, t) { - return B(e) === "task_locked" ? d("tasks_projects.tasks.locked") : d(`tasks_projects.tasks.${t}`); + function re(e, t) { + return gt(e) === "task_locked" ? d("tasks_projects.tasks.locked") : d(`tasks_projects.tasks.${t}`); } - async function ae() { + async function ie() { let e = l.task; if (!(e === null || O.value) && window.confirm(d("tasks_projects.tasks.delete_confirm", { name: e.name }))) { O.value = !0; try { - await An(l.client, e.id), u("deleted", e); + await ur(l.client, e.id), u("deleted", e); } catch (e) { - l.notify("error", z(e, ie(e, "delete_failed"))); + l.notify("error", H(e, re(e, "delete_failed"))); } finally { O.value = !1; } } } return (t, n) => { - let l = x("BaseIcon"), m = x("BaseInput"), v = x("BaseInputGroup"), y = x("BaseSelectInput"), E = x("BaseDatePicker"), ee = x("BaseInputGrid"), R = x("BaseSwitch"), ne = x("BaseTextarea"), ie = x("BaseButton"), oe = x("BaseModal"); - return _(), r(oe, { + let l = x("BaseIcon"), m = x("BaseInput"), v = x("BaseInputGroup"), y = x("BaseSelectInput"), E = x("BaseDatePicker"), R = x("BaseInputGrid"), z = x("BaseSwitch"), B = x("BaseTextarea"), te = x("BaseButton"), re = x("BaseModal"); + return _(), r(re, { show: e.show, onClose: n[12] ||= (e) => u("close") }, { - header: D(() => [o("div", Ui, [o("span", null, [s(S(P.value) + " ", 1), e.task ? (_(), a("span", Wi, "#" + S(e.task.number), 1)) : i("", !0)]), c(l, { + header: D(() => [o("div", pa, [o("span", null, [s(S(P.value) + " ", 1), e.task ? (_(), a("span", ma, "#" + S(e.task.number), 1)) : i("", !0)]), c(l, { name: "XMarkIcon", class: "h-6 w-6 cursor-pointer text-subtle hover:text-body", onClick: n[0] ||= (e) => u("close") })])]), - default: D(() => [o("form", { onSubmit: A(re, ["prevent"]) }, [o("div", Gi, [ + default: D(() => [o("form", { onSubmit: A(ne, ["prevent"]) }, [o("div", ha, [ c(v, { label: C(d)("tasks_projects.tasks.fields.name"), error: w.value.name, @@ -2716,7 +2877,7 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { }, null, 8, ["modelValue", "invalid"])]), _: 1 }, 8, ["label", "error"]), - c(ee, null, { + c(R, null, { default: D(() => [ e.lockProject ? i("", !0) : (_(), r(v, { key: 0, @@ -2747,7 +2908,7 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { "help-text": C(d)("tasks_projects.tasks.fields.customer_help") }, { default: D(() => [c(m, { - "model-value": `#${b.value}`, + "model-value": C($t)(b.value), type: "text", disabled: "" }, null, 8, ["model-value"])]), @@ -2806,7 +2967,7 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { }, { default: D(() => [c(E, { "model-value": f.dueDate, - "onUpdate:modelValue": te + "onUpdate:modelValue": ee }, null, 8, ["model-value"])]), _: 1 }, 8, ["label", "error"]), @@ -2852,7 +3013,7 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { label: C(d)("tasks_projects.tasks.fields.billable"), error: w.value.billable }, { - default: D(() => [c(R, { + default: D(() => [c(z, { modelValue: f.billable, "onUpdate:modelValue": n[8] ||= (e) => f.billable = e, class: "mt-1" @@ -2864,7 +3025,7 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { label: C(d)("tasks_projects.tasks.fields.description"), error: w.value.description }, { - default: D(() => [c(ne, { + default: D(() => [c(B, { modelValue: f.description, "onUpdate:modelValue": n[9] ||= (e) => f.description = e, row: 3, @@ -2881,24 +3042,24 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { name: k.value ? "ChevronUpIcon" : "ChevronDownIcon", class: "h-4 w-4" }, null, 8, ["name"]), s(" " + S(k.value ? C(d)("tasks_projects.tasks.fewer_fields") : C(d)("tasks_projects.tasks.all_fields")), 1)])) : i("", !0) - ]), o("div", Ki, [N.value ? (_(), r(ie, { + ]), o("div", ga, [N.value ? (_(), r(te, { key: 0, type: "button", variant: "danger", loading: O.value, disabled: O.value, - onClick: ae + onClick: ie }, { default: D(() => [s(S(C(d)("tasks_projects.general.delete")), 1)]), _: 1 - }, 8, ["loading", "disabled"])) : (_(), a("span", qi)), o("div", Ji, [c(ie, { + }, 8, ["loading", "disabled"])) : (_(), a("span", _a)), o("div", va, [c(te, { type: "button", variant: "primary-outline", onClick: n[11] ||= (e) => u("close") }, { default: D(() => [s(S(C(d)("tasks_projects.general.cancel")), 1)]), _: 1 - }), c(ie, { + }), c(te, { type: "submit", variant: "primary", loading: T.value, @@ -2907,106 +3068,11 @@ var Ti = { class: "mt-4 flex flex-wrap items-end gap-3" }, Ei = { default: D(() => [s(S(N.value ? C(d)("tasks_projects.general.update") : C(d)("tasks_projects.general.save")), 1)]), _: 1 }, 8, ["loading", "disabled"])])])], 32)]), - _: 1 - }, 8, ["show"]); - }; - } -}), Xi = "/api/v1/tasks-projects", Zi = { - timeEntries: `${Xi}/time-entries`, - timeEntry: (e) => `${Xi}/time-entries/${e}`, - timer: `${Xi}/timer`, - timerStart: `${Xi}/timer/start`, - timerStop: `${Xi}/timer/stop`, - taskStatuses: `${Xi}/task-statuses`, - taskStatus: (e) => `${Xi}/task-statuses/${e}`, - reorderTaskStatuses: `${Xi}/task-statuses/reorder`, - tasks: `${Xi}/tasks`, - task: (e) => `${Xi}/tasks/${e}`, - members: `${Xi}/members`, - settings: `${Xi}/settings` -}, Qi = { bootstrap: "/api/v1/bootstrap" }, $i = 100, ea = 5, ta = 10; -async function na(e, t) { - let { data: n } = await e.get(Zi.timeEntries, { params: t }); - return n; -} -async function ra(e, t) { - let n = []; - for (let r = 1; r <= ea; r += 1) { - let i = await na(e, { - ...t, - page: r, - limit: $i - }); - if (n.push(...i.data ?? []), !i.meta || r >= i.meta.last_page) break; + _: 1 + }, 8, ["show"]); + }; } - return n; -} -async function ia(e, t) { - let { data: n } = await e.post(Zi.timeEntries, t); - return n.data; -} -async function aa(e, t, n) { - let { data: r } = await e.put(Zi.timeEntry(t), n); - return r.data; -} -async function oa(e, t) { - await e.delete(Zi.timeEntry(t)); -} -async function sa(e) { - let { data: t } = await e.get(Zi.timer); - return t?.data ?? null; -} -async function ca(e, t) { - let { data: n } = await e.post(Zi.timerStart, t); - return n.data; -} -async function la(e) { - let { data: t } = await e.post(Zi.timerStop); - return t.data; -} -async function ua(e) { - await e.delete(Zi.timer); -} -async function da(e) { - let { data: t } = await e.get(Zi.taskStatuses); - return t.data ?? []; -} -async function fa(e, t) { - let { data: n } = await e.post(Zi.taskStatuses, t); - return n.data; -} -async function pa(e, t, n) { - let { data: r } = await e.put(Zi.taskStatus(t), n); - return r.data; -} -async function ma(e, t) { - await e.delete(Zi.taskStatus(t)); -} -async function ha(e, t) { - let { data: n } = await e.post(Zi.reorderTaskStatuses, { ids: t }); - return n.data ?? []; -} -async function ga(e, t, n = ta) { - let r = { limit: n }; - t.trim() !== "" && (r.search = t.trim()); - let { data: i } = await e.get(Zi.tasks, { params: r }); - return i.data ?? []; -} -async function _a(e, t) { - let { data: n } = await e.get(Zi.task(t)); - return n.data; -} -async function va(e) { - let { data: t } = await e.get(Zi.settings); - return t.data; -} -async function ya(e) { - let { data: t } = await e.get(Qi.bootstrap), n = t?.current_user?.id; - return typeof n == "number" ? n : null; -} -//#endregion -//#region resources/js/stores/session.ts -var ba = { +}), ba = { default_rate: 0, rounding_minutes: 1, rounding_direction: "nearest", @@ -3039,7 +3105,7 @@ var ba = { async function Sa(e) { if (xa.adminMode) return; xa.loading = !0; - let [t, n] = await Promise.all([ya(e).catch(() => null), va(e).catch(() => null)]); + let [t, n] = await Promise.all([We(e).catch(() => null), Ue(e).catch(() => null)]); xa.userId = t, xa.settings = Ta(n), xa.loading = !1; } function Ca() { @@ -3082,110 +3148,58 @@ function ka(e) { return typeof e == "number" && Number.isInteger(e) && e >= 0 && e <= 6 ? e : ba.week_start; } //#endregion -//#region resources/js/stores/tasks.ts -var Aa = v({}), ja = /* @__PURE__ */ new Set(), Ma = 5, Na = { - logged_minutes: 0, - billable_minutes: 0, - unbilled_minutes: 0, - unbilled_amount: 0, - invoiced: "none", - running: [] -}, Pa = y(0), Fa = v({}); -function Ia(e) { - return e === null ? "" : Aa[e] ?? `#${e}`; -} -function La(e) { - e && typeof e.id == "number" && typeof e.name == "string" && (Aa[e.id] = e.name); -} -async function Ra(e, t) { - let n = [...new Set(t)].filter((e) => typeof e == "number" && Aa[e] === void 0 && !ja.has(e)); - for (let e of n) ja.add(e); - for (let t = 0; t < n.length; t += Ma) await Promise.all(n.slice(t, t + Ma).map(async (t) => { - try { - La(await _a(e, t)); - } catch {} finally { - ja.delete(t); - } - })); -} -var za = Pa; -function U() { - Pa.value += 1; -} -function Ba(e, t) { - Fa[e] = { - ...Fa[e] ?? {}, - ...t - }; -} -function Va(e) { - if (!e || typeof e.id != "number") return Na; - let t = e.time ?? Na; - return { - ...Na, - ...t, - running: Array.isArray(t.running) ? t.running : [], - ...Fa[e.id] ?? {} - }; -} -function Ha() { - for (let e of Object.keys(Aa)) delete Aa[Number(e)]; - for (let e of Object.keys(Fa)) delete Fa[Number(e)]; - ja.clear(); -} -//#endregion //#region resources/js/support/time.ts -var Ua = 60, Wa = 60, Ga = 7; -function Ka(e) { - let t = Number.isFinite(e) && e > 0 ? Math.floor(e) : 0, n = Math.floor(t / 3600), r = Math.floor(t % 3600 / Wa), i = t % Wa; - return `${n}:${lo(r)}:${lo(i)}`; +var Aa = 60, ja = 60, Ma = 7; +function Na(e) { + let t = Number.isFinite(e) && e > 0 ? Math.floor(e) : 0, n = Math.floor(t / 3600), r = Math.floor(t % 3600 / ja), i = t % ja; + return `${n}:${Xa(r)}:${Xa(i)}`; } -function qa(e) { +function Pa(e) { let t = e !== null && Number.isFinite(e) && e > 0 ? Math.round(e) : 0; - return `${Math.floor(t / Ua)}:${lo(t % Ua)}`; + return `${Math.floor(t / Aa)}:${Xa(t % Aa)}`; } -function Ja(e) { +function Fa(e) { let t = e.trim(); if (t === "") return null; let n = /^(\d+):([0-5]?\d)$/.exec(t); - if (n) return Number(n[1]) * Ua + Number(n[2]); + if (n) return Number(n[1]) * Aa + Number(n[2]); if (!/^\d+([.,]\d+)?$/.test(t)) return null; let r = Number(t.replace(",", ".")); - return Number.isNaN(r) ? null : Math.round(r * Ua); + return Number.isNaN(r) ? null : Math.round(r * Aa); } -function Ya(e) { - let t = oo(e); - return t === null ? "" : no(t); +function Ia(e) { + let t = qa(e); + return t === null ? "" : Ua(t); } -function Xa(e) { - let t = oo(e); - return t === null ? "" : `${lo(t.getHours())}:${lo(t.getMinutes())}`; +function La(e) { + let t = qa(e); + return t === null ? "" : `${Xa(t.getHours())}:${Xa(t.getMinutes())}`; } -function Za(e, t = "09:00") { - let n = so(e), r = /^(\d{1,2}):([0-5]\d)$/.exec(t.trim()); +function Ra(e, t = "09:00") { + let n = Ja(e), r = /^(\d{1,2}):([0-5]\d)$/.exec(t.trim()); if (n === null || r === null) return null; let i = Number(r[1]); return i > 23 ? null : (n.setHours(i, Number(r[2]), 0, 0), n.toISOString()); } -function Qa(e, t) { +function za(e, t) { let n = new Date(e); - return n.setTime(n.getTime() + t * Wa * 1e3), n.toISOString(); + return n.setTime(n.getTime() + t * ja * 1e3), n.toISOString(); } -function $a(e, t) { - let n = Number.isInteger(t) && t >= 0 && t <= 6 ? t : 1, r = co(e), i = (r.getDay() - n + Ga) % Ga; +function Ba(e, t) { + let n = Number.isInteger(t) && t >= 0 && t <= 6 ? t : 1, r = Ya(e), i = (r.getDay() - n + Ma) % Ma; return r.setDate(r.getDate() - i), r; } -function eo(e) { - return Array.from({ length: Ga }, (t, n) => to(e, n)); +function Va(e) { + return Array.from({ length: Ma }, (t, n) => Ha(e, n)); } -function to(e, t) { - let n = co(e); +function Ha(e, t) { + let n = Ya(e); return n.setDate(n.getDate() + t), n; } -function no(e) { - return `${e.getFullYear()}-${lo(e.getMonth() + 1)}-${lo(e.getDate())}`; +function Ua(e) { + return `${e.getFullYear()}-${Xa(e.getMonth() + 1)}-${Xa(e.getDate())}`; } -function ro(e) { +function Wa(e) { return { weekday: e.toLocaleDateString(void 0, { weekday: "short" }), day: e.toLocaleDateString(void 0, { @@ -3194,167 +3208,167 @@ function ro(e) { }) }; } -function io(e) { - return no(e) === no(/* @__PURE__ */ new Date()); +function Ga(e) { + return Ua(e) === Ua(/* @__PURE__ */ new Date()); } -function ao(e, t) { - let n = oo(e); +function Ka(e, t) { + let n = qa(e); return n === null ? 0 : Math.max(0, Math.floor((t - n.getTime()) / 1e3)); } -function oo(e) { +function qa(e) { if (!e) return null; let t = new Date(e); return Number.isNaN(t.getTime()) ? null : t; } -function so(e) { +function Ja(e) { let t = /^(\d{4})-(\d{2})-(\d{2})/.exec(e.trim()); if (t === null) return null; let n = new Date(Number(t[1]), Number(t[2]) - 1, Number(t[3]), 0, 0, 0, 0); return Number.isNaN(n.getTime()) ? null : n; } -function co(e) { +function Ya(e) { let t = new Date(e.getTime()); return t.setHours(0, 0, 0, 0), t; } -function lo(e) { +function Xa(e) { return String(e).padStart(2, "0"); } //#endregion //#region resources/js/stores/timer.ts -var W = v({ +var G = v({ running: null, busy: !1 -}), uo = v({ now: Date.now() }), fo, po = 0; -function mo() { - uo.now = Date.now(); +}), Za = v({ now: Date.now() }), Qa, $a = 0; +function eo() { + Za.now = Date.now(); } -function ho() { - po += 1, fo === void 0 && (mo(), fo = setInterval(mo, 1e3)); +function to() { + $a += 1, Qa === void 0 && (eo(), Qa = setInterval(eo, 1e3)); } -function go() { - po = Math.max(0, po - 1), po === 0 && fo !== void 0 && (clearInterval(fo), fo = void 0); +function no() { + $a = Math.max(0, $a - 1), $a === 0 && Qa !== void 0 && (clearInterval(Qa), Qa = void 0); } -function _o() { - return ho(), g(go, !0), n(() => uo.now); +function ro() { + return to(), g(no, !0), n(() => Za.now); } -var vo = !1; -function yo(e, t) { - if (W.running = e && typeof e.id == "number" ? e : null, W.running === null) { - vo && (vo = !1, go()); +var io = !1; +function ao(e, t) { + if (G.running = e && typeof e.id == "number" ? e : null, G.running === null) { + io && (io = !1, no()); return; } - vo || (vo = !0, ho()), t && typeof W.running.task_id == "number" && Ra(t, [W.running.task_id]); + io || (io = !0, to()), t && typeof G.running.task_id == "number" && $e(t, [G.running.task_id]); } -function bo(e, t, n) { - e?.notify("error", z(t, e.t(n))); +function oo(e, t, n) { + e?.notify("error", H(t, e.t(n))); } -function xo(e) { - Ba(e.task_id, { running: [{ +function so(e) { + tt(e.task_id, { running: [{ entry_id: e.id, user_id: e.user_id, started_at: e.started_at }] }); } -var G = { +var K = { get running() { - return W.running; + return G.running; }, get runningTaskId() { - let e = W.running?.task_id; + let e = G.running?.task_id; return typeof e == "number" ? e : null; }, get elapsedSeconds() { - return W.running === null ? 0 : ao(W.running.started_at, uo.now); + return G.running === null ? 0 : Ka(G.running.started_at, Za.now); }, get busy() { - return W.busy; + return G.busy; }, isRunningOn(e) { - return W.running !== null && W.running.task_id === e; + return G.running !== null && G.running.task_id === e; }, async refresh(e) { try { - yo(await sa(e), e); + ao(await Me(e), e); } catch { - yo(null); + ao(null); } }, async start(e, t, n = null, r) { - if (W.busy) return null; - W.busy = !0; + if (G.busy) return null; + G.busy = !0; try { - let r = await ca(e, { + let r = await Ne(e, { task_id: t, description: n }); - return yo(r, e), xo(r), U(), r; + return ao(r, e), so(r), V(), r; } catch (t) { - return ue(t) ? (r?.notify("warning", r.t("tasks_projects.timer.already_running")), await this.refresh(e)) : bo(r, t, "tasks_projects.timer.start_failed"), null; + return _t(t) ? (r?.notify("warning", r.t("tasks_projects.timer.already_running")), await this.refresh(e)) : oo(r, t, "tasks_projects.timer.start_failed"), null; } finally { - W.busy = !1; + G.busy = !1; } }, async startOnTask(e, t, n = null, r) { - if (W.busy) return null; - W.busy = !0; + if (G.busy) return null; + G.busy = !0; try { - let r = await Mn(e, t, n); - return yo(r, e), xo(r), U(), r; + let r = await fr(e, t, n); + return ao(r, e), so(r), V(), r; } catch (t) { - return B(t) === "timer_already_running" ? (r?.notify("warning", r.t("tasks_projects.timer.already_running")), await this.refresh(e)) : bo(r, t, "tasks_projects.timer.start_failed"), null; + return gt(t) === "timer_already_running" ? (r?.notify("warning", r.t("tasks_projects.timer.already_running")), await this.refresh(e)) : oo(r, t, "tasks_projects.timer.start_failed"), null; } finally { - W.busy = !1; + G.busy = !1; } }, async stop(e, t) { - if (W.busy || W.running === null) return null; - let n = W.running.task_id; - W.busy = !0; + if (G.busy || G.running === null) return null; + let n = G.running.task_id; + G.busy = !0; try { - let t = await la(e); - return yo(null), Ba(n, { running: [] }), U(), t; + let t = await Pe(e); + return ao(null), tt(n, { running: [] }), V(), t; } catch (n) { - return bo(t, n, "tasks_projects.timer.stop_failed"), await this.refresh(e), null; + return oo(t, n, "tasks_projects.timer.stop_failed"), await this.refresh(e), null; } finally { - W.busy = !1; + G.busy = !1; } }, async stopOnTask(e, t, n) { - if (W.busy) return null; - W.busy = !0; + if (G.busy) return null; + G.busy = !0; try { - let n = await Nn(e, t); - return yo(null), Ba(t, { running: [] }), U(), n; + let n = await pr(e, t); + return ao(null), tt(t, { running: [] }), V(), n; } catch (t) { - return B(t) === "timer_mismatch" ? n?.notify("warning", n.t("tasks_projects.timer.mismatch")) : bo(n, t, "tasks_projects.timer.stop_failed"), await this.refresh(e), null; + return gt(t) === "timer_mismatch" ? n?.notify("warning", n.t("tasks_projects.timer.mismatch")) : oo(n, t, "tasks_projects.timer.stop_failed"), await this.refresh(e), null; } finally { - W.busy = !1; + G.busy = !1; } }, async discard(e, t) { - if (W.busy || W.running === null) return !1; - let n = W.running.task_id; - W.busy = !0; + if (G.busy || G.running === null) return !1; + let n = G.running.task_id; + G.busy = !0; try { - return await ua(e), yo(null), Ba(n, { running: [] }), U(), !0; + return await Fe(e), ao(null), tt(n, { running: [] }), V(), !0; } catch (n) { - return bo(t, n, "tasks_projects.timer.discard_failed"), await this.refresh(e), !1; + return oo(t, n, "tasks_projects.timer.discard_failed"), await this.refresh(e), !1; } finally { - W.busy = !1; + G.busy = !1; } }, reset() { - W.busy = !1, yo(null); + G.busy = !1, ao(null); } -}, So = { class: "flex items-center gap-1.5" }, Co = [ +}, co = { class: "flex items-center gap-1.5" }, lo = [ "disabled", "title", "aria-label" -], wo = ["title", "aria-label"], To = ["disabled", "title"], Eo = [ +], uo = ["title", "aria-label"], fo = ["disabled", "title"], po = [ "disabled", "title", "aria-label" -], Do = ["title"], Oo = /* @__PURE__ */ l({ +], mo = ["title"], ho = /* @__PURE__ */ l({ __name: "TaskRunControl", props: { client: {}, @@ -3364,19 +3378,19 @@ var G = { size: { default: "sm" } }, setup(t) { - let r = t, i = V(), l = _o(), u = n(() => ({ + let r = t, i = B(), l = ro(), u = n(() => ({ notify: r.notify, t: i - })), d = n(() => G.isRunningOn(r.task.id)), p = n(() => G.runningTaskId !== null && !d.value), m = n(() => Ia(G.runningTaskId)), h = n(() => Va(r.task).running.filter((e) => e.user_id !== xa.userId && e.entry_id !== G.running?.id)), g = n(() => Ka(G.elapsedSeconds)), v = n(() => r.size === "md" ? "h-5 w-5" : "h-4 w-4"), y = n(() => r.size === "md" ? "p-2" : "p-1.5"); + })), d = n(() => K.isRunningOn(r.task.id)), p = n(() => K.runningTaskId !== null && !d.value), m = n(() => Ze(K.runningTaskId)), h = n(() => nt(r.task).running.filter((e) => e.user_id !== xa.userId && e.entry_id !== K.running?.id)), g = n(() => Na(K.elapsedSeconds)), v = n(() => r.size === "md" ? "h-5 w-5" : "h-4 w-4"), y = n(() => r.size === "md" ? "p-2" : "p-1.5"); function w(e) { return r.members.find((t) => t.id === e)?.name ?? `#${e}`; } function T(e) { let t = r.members.find((t) => t.id === e); - return t ? ye(t.name) : "?"; + return t ? pt(t.name) : "?"; } function E(e) { - return Ka(ao(e.started_at, l.value)); + return Na(Ka(e.started_at, l.value)); } function D(e) { return i("tasks_projects.timer.running_by", { @@ -3385,31 +3399,31 @@ var G = { }); } async function O() { - await G.startOnTask(r.client, r.task.id, null, u.value) !== null && r.notify("success", i("tasks_projects.timer.started", { name: r.task.name })); + await K.startOnTask(r.client, r.task.id, null, u.value) !== null && r.notify("success", i("tasks_projects.timer.started", { name: r.task.name })); } async function k() { - let e = await G.stopOnTask(r.client, r.task.id, u.value); + let e = await K.stopOnTask(r.client, r.task.id, u.value); e !== null && r.notify("success", i("tasks_projects.timer.stopped", { name: r.task.name, - duration: qa(e.duration_minutes) + duration: Pa(e.duration_minutes) })); } async function j() { - await G.stop(r.client, u.value) !== null && await O(); + await K.stop(r.client, u.value) !== null && await O(); } return (n, r) => { let l = x("BaseIcon"); - return _(), a("div", So, [d.value ? (_(), a(e, { key: 0 }, [o("button", { + return _(), a("div", co, [d.value ? (_(), a(e, { key: 0 }, [o("button", { type: "button", class: f(["rounded-md text-status-red hover:bg-hover disabled:opacity-50", y.value]), - disabled: C(G).busy, + disabled: C(K).busy, title: C(i)("tasks_projects.timer.stop_on", { name: t.task.name }), "aria-label": C(i)("tasks_projects.timer.stop_on", { name: t.task.name }), onClick: A(k, ["stop"]) }, [c(l, { name: "StopIcon", class: f(v.value) - }, null, 8, ["class"])], 10, Co), o("span", { class: f(["font-medium tabular-nums text-primary-500", t.size === "md" ? "text-base" : "text-xs"]) }, S(g.value), 3)], 64)) : p.value ? (_(), a(e, { key: 1 }, [o("button", { + }, null, 8, ["class"])], 10, lo), o("span", { class: f(["font-medium tabular-nums text-primary-500", t.size === "md" ? "text-base" : "text-xs"]) }, S(g.value), 3)], 64)) : p.value ? (_(), a(e, { key: 1 }, [o("button", { type: "button", class: f(["cursor-not-allowed rounded-md text-subtle", y.value]), disabled: "", @@ -3418,44 +3432,42 @@ var G = { }, [c(l, { name: "PlayIcon", class: f(v.value) - }, null, 8, ["class"])], 10, wo), o("button", { + }, null, 8, ["class"])], 10, uo), o("button", { type: "button", class: "rounded-md px-1.5 py-0.5 text-[11px] font-medium text-primary-500 hover:bg-hover disabled:opacity-50", - disabled: C(G).busy, + disabled: C(K).busy, title: C(i)("tasks_projects.timer.stop_and_start"), onClick: A(j, ["stop"]) - }, S(C(i)("tasks_projects.timer.stop_and_start")), 9, To)], 64)) : (_(), a("button", { + }, S(C(i)("tasks_projects.timer.stop_and_start")), 9, fo)], 64)) : (_(), a("button", { key: 2, type: "button", class: f(["rounded-md text-primary-500 hover:bg-hover disabled:opacity-50", y.value]), - disabled: C(G).busy, + disabled: C(K).busy, title: C(i)("tasks_projects.timer.start_on", { name: t.task.name }), "aria-label": C(i)("tasks_projects.timer.start_on", { name: t.task.name }), onClick: A(O, ["stop"]) }, [c(l, { name: "PlayIcon", class: f(v.value) - }, null, 8, ["class"])], 10, Eo)), (_(!0), a(e, null, b(h.value, (e) => (_(), a("span", { + }, null, 8, ["class"])], 10, po)), (_(!0), a(e, null, b(h.value, (e) => (_(), a("span", { key: e.entry_id, class: "flex items-center gap-1 rounded-full bg-surface-tertiary px-1.5 py-0.5 text-[11px] text-muted", title: D(e) }, [c(l, { name: "ClockIcon", class: "h-3.5 w-3.5 text-primary-500" - }), s(" " + S(T(e.user_id)), 1)], 8, Do))), 128))]); + }), s(" " + S(T(e.user_id)), 1)], 8, mo))), 128))]); }; } -}), ko = { class: "relative table-container" }, Ao = { class: "inline-flex items-center whitespace-nowrap" }, jo = { class: "tabular-nums" }, Mo = { - key: 1, - class: "text-subtle" -}, No = { +}), go = { class: "relative table-container" }, _o = { class: "inline-flex items-center whitespace-nowrap" }, vo = { class: "tabular-nums" }, yo = { key: 1, class: "text-subtle" -}, Po = ["title"], Fo = 10, Io = /* @__PURE__ */ l({ +}, bo = ["title"], xo = 10, So = "whitespace-nowrap px-3 py-3 text-left text-xs font-medium text-muted uppercase tracking-wider", Co = "px-3 py-4 text-sm text-muted whitespace-nowrap", wo = /* @__PURE__ */ l({ __name: "TaskList", props: { client: {}, notify: {}, + router: {}, filters: {}, statuses: {}, members: {}, @@ -3463,15 +3475,14 @@ var G = { projectId: { default: null } }, emits: ["changed"], - setup(e, { expose: t, emit: i }) { - let l = e, u = i, d = { + setup(t, { expose: l, emit: u }) { + let d = t, m = u, h = { number: "number", - name: "name", - due_date: "due_date" - }, m = V(), h = y(null), g = y(!0), v = y(0), b = y([]), w = y([]), k = y(!1), A = y(!1), j = y(null), M = y({}), N = y(null), P = n(() => l.projects.map((e) => ({ + name: "name" + }, g = B(), v = y(null), b = y(!0), w = y(0), k = y([]), A = y([]), j = y(!1), N = y(!1), P = y(null), F = y({}), I = y(null), L = n(() => d.projects.map((e) => ({ id: e.id, label: e.name - }))), F = n(() => l.filters.search !== "" || l.filters.status !== "" || l.filters.user !== "" || l.projectId === null && l.filters.project !== ""), I = n(() => !g.value && v.value === 0 && !F.value), L = n(() => [ + }))), R = n(() => M.busy), z = n(() => M.allowed), ee = n(() => d.filters.search !== "" || d.filters.status !== "" || d.filters.user !== "" || d.projectId === null && d.filters.project !== ""), te = n(() => !b.value && w.value === 0 && !ee.value), ne = n(() => [ { key: "select", label: "", @@ -3480,14 +3491,14 @@ var G = { }, { key: "number", - label: m("tasks_projects.tasks.columns.number"), + label: g("tasks_projects.tasks.columns.number"), sortable: !0, sortBy: "number", tdClass: "text-muted" }, { key: "name", - label: m("tasks_projects.tasks.columns.name"), + label: g("tasks_projects.tasks.columns.name"), sortable: !0, sortBy: "name", thClass: "extra", @@ -3495,296 +3506,333 @@ var G = { }, { key: "status", - label: m("tasks_projects.tasks.columns.status"), + label: g("tasks_projects.tasks.columns.status"), sortable: !1 }, { key: "assignee", - label: m("tasks_projects.tasks.columns.assignee"), + label: g("tasks_projects.tasks.columns.assignee"), sortable: !1 }, { key: "logged", - label: m("tasks_projects.tasks.columns.logged"), + label: g("tasks_projects.tasks.columns.logged"), sortable: !1 }, { key: "unbilled", - label: m("tasks_projects.tasks.columns.unbilled"), + label: g("tasks_projects.tasks.columns.unbilled"), sortable: !1 }, { key: "invoiced", - label: m("tasks_projects.tasks.columns.invoiced"), + label: g("tasks_projects.tasks.columns.invoiced"), sortable: !1 }, { key: "timer", - label: m("tasks_projects.tasks.columns.timer"), + label: g("tasks_projects.tasks.columns.timer"), sortable: !1 }, - { - key: "due_date", - label: m("tasks_projects.tasks.columns.due_date"), - sortable: !0, - sortBy: "due_date" - }, { key: "actions", - label: m("tasks_projects.general.actions"), + label: g("tasks_projects.general.actions"), sortable: !1, tdClass: "text-right text-sm font-medium" } - ]); - E(() => vi(l.filters), () => R()), E(() => l.projectId, () => R()), E(za, () => R(!0)); - async function ee({ page: e, sort: t }) { - let n = hn(t, d), r = { + ].map((e) => ({ + defaultThClass: So, + defaultTdClass: Co, + ...e + }))); + E(() => Ui(d.filters), () => ie()), E(() => d.projectId, () => ie()), E(et, () => ie(!0)); + async function re({ page: e, sort: t }) { + let n = Vt(t, h), r = { page: e, - limit: Fo, - ...bi(l.filters, { projectId: l.projectId }), + limit: xo, + ...Gi(d.filters, { projectId: d.projectId }), ...n }; - g.value = !0; + b.value = !0; try { - let e = await Dn(l.client, r), t = e.data ?? [], n = e.meta; - return v.value = n?.total ?? t.length, b.value = t, w.value = w.value.filter((e) => t.some((t) => t.id === e)), { + let e = await sr(d.client, r), t = e.data ?? [], n = e.meta; + return w.value = n?.total ?? t.length, k.value = t, A.value = A.value.filter((e) => t.some((t) => t.id === e)), { data: t, pagination: { totalPages: n?.last_page ?? 1, currentPage: n?.current_page ?? 1, totalCount: n?.total ?? t.length, - limit: n?.per_page ?? Fo + limit: n?.per_page ?? xo } }; } catch (e) { - return l.notify("error", z(e, m("tasks_projects.tasks.load_failed"))), b.value = [], { + return d.notify("error", H(e, g("tasks_projects.tasks.load_failed"))), k.value = [], { data: [], pagination: { totalPages: 1, currentPage: 1, totalCount: 0, - limit: Fo + limit: xo } }; } finally { - g.value = !1; + b.value = !1; } } - function R(e = !1) { - h.value?.refresh(e); + function ie(e = !1) { + v.value?.refresh(e); } - function te(e) { - return w.value.includes(e.id); + function ae(e) { + return A.value.includes(e.id); } - function ne(e) { - w.value = te(e) ? w.value.filter((t) => t !== e.id) : [...w.value, e.id]; + function oe(e) { + A.value = ae(e) ? A.value.filter((t) => t !== e.id) : [...A.value, e.id]; } - function re() { - w.value = b.value.map((e) => e.id); + function se() { + A.value = k.value.map((e) => e.id); } - function ie() { - w.value = []; + function ce() { + A.value = []; } - function ae() { - j.value = null, M.value = { project_id: l.projectId }, A.value = !0; + function le() { + P.value = null, F.value = { project_id: d.projectId }, N.value = !0; } - function oe(e) { - j.value = e, M.value = {}, A.value = !0; + function ue(e) { + P.value = e, F.value = {}, N.value = !0; } - function se(e) { - let t = j.value ? m("tasks_projects.tasks.updated", { name: e.name }) : m("tasks_projects.tasks.created", { name: e.name }); - A.value = !1, j.value = null, l.notify("success", t), U(), u("changed"); + function de(e) { + let t = P.value ? g("tasks_projects.tasks.updated", { name: e.name }) : g("tasks_projects.tasks.created", { name: e.name }); + N.value = !1, P.value = null, d.notify("success", t), V(), m("changed"); } - function ce(e) { - A.value = !1, j.value = null, l.notify("success", m("tasks_projects.tasks.deleted", { name: e.name })), U(), u("changed"); + function fe(e) { + N.value = !1, P.value = null, d.notify("success", g("tasks_projects.tasks.deleted", { name: e.name })), V(), m("changed"); } - function le(e) { - return l.statuses.find((t) => t.id === e.task_status_id) ?? null; + function pe(e) { + return d.statuses.find((t) => t.id === e.task_status_id) ?? null; } - function B(e) { - return e.assignee_id === null ? m("tasks_projects.tasks.unassigned") : l.members.find((t) => t.id === e.assignee_id)?.name ?? `#${e.assignee_id}`; + function me(e) { + return e.assignee_id === null ? g("tasks_projects.tasks.unassigned") : d.members.find((t) => t.id === e.assignee_id)?.name ?? `#${e.assignee_id}`; } - function ue(e) { - return qa(Va(e).logged_minutes); + function he(e) { + return Pa(nt(e).logged_minutes); + } + function ge(e) { + return nt(e).invoiced === "uninvoiced"; + } + function _e(e) { + return nt(e).invoiced === "invoiced" ? g("tasks_projects.tasks.already_invoiced") : g("tasks_projects.tasks.nothing_to_invoice"); + } + let ve = n(() => ({ + client: d.client, + router: d.router, + notify: d.notify, + t: g + })); + async function ye(e) { + if (!R.value) { + I.value = e.id; + try { + await bt(ve.value, { taskIds: [e.id] }); + } finally { + I.value = null; + } + } } - async function de(e) { - if (window.confirm(m("tasks_projects.tasks.delete_confirm", { name: e.name }))) { - N.value = e.id; + async function be() { + R.value || A.value.length === 0 || await bt(ve.value, { taskIds: [...A.value] }) && ce(); + } + async function xe(e) { + if (window.confirm(g("tasks_projects.tasks.delete_confirm", { name: e.name }))) { + I.value = e.id; try { - await An(l.client, e.id), l.notify("success", m("tasks_projects.tasks.deleted", { name: e.name })), U(), u("changed"); + await ur(d.client, e.id), d.notify("success", g("tasks_projects.tasks.deleted", { name: e.name })), V(), m("changed"); } catch (e) { - l.notify("error", z(e, m("tasks_projects.tasks.delete_failed"))); + d.notify("error", H(e, g("tasks_projects.tasks.delete_failed"))); } finally { - N.value = null; + I.value = null; } } } - async function fe(e) { - await me({ + async function Se(e) { + await we({ action: "status", - ids: [...w.value], + ids: [...A.value], task_status_id: e }, "applied"); } - async function pe() { - let e = w.value.length; - window.confirm(m("tasks_projects.tasks.bulk.delete_confirm", { count: e })) && await me({ + async function Ce() { + let e = A.value.length; + window.confirm(g("tasks_projects.tasks.bulk.delete_confirm", { count: e })) && await we({ action: "delete", - ids: [...w.value] + ids: [...A.value] }, "deleted"); } - async function me(e, t) { - if (!(k.value || e.ids.length === 0)) { - k.value = !0; + async function we(e, t) { + if (!(j.value || e.ids.length === 0)) { + j.value = !0; try { - let n = await Fn(l.client, e); - n.failed.length > 0 ? l.notify("warning", m("tasks_projects.tasks.bulk.partial", { + let n = await hr(d.client, e); + n.failed.length > 0 ? d.notify("warning", g("tasks_projects.tasks.bulk.partial", { count: n.updated, failed: n.failed.length - })) : n.updated === 0 ? l.notify("warning", m("tasks_projects.tasks.bulk.nothing")) : l.notify("success", m(`tasks_projects.tasks.bulk.${t}`, { count: n.updated })), ie(), U(), u("changed"); + })) : n.updated === 0 ? d.notify("warning", g("tasks_projects.tasks.bulk.nothing")) : d.notify("success", g(`tasks_projects.tasks.bulk.${t}`, { count: n.updated })), ce(), V(), m("changed"); } catch (e) { - l.notify("error", z(e, m("tasks_projects.tasks.bulk.failed"))); + d.notify("error", H(e, g("tasks_projects.tasks.bulk.failed"))); } finally { - k.value = !1; + j.value = !1; } } } - return t({ - openCreate: ae, - refresh: R - }), (t, n) => { - let i = x("BaseIcon"), l = x("BaseButton"), u = x("BaseEmptyPlaceholder"), d = x("BaseCheckbox"), g = x("router-link"), v = x("BaseFormatMoney"), y = x("BaseDropdownItem"), b = x("BaseDropdown"), E = x("BaseTable"); + return l({ + openCreate: le, + refresh: ie + }), (n, l) => { + let u = x("BaseIcon"), d = x("BaseButton"), m = x("BaseEmptyPlaceholder"), h = x("BaseCheckbox"), y = x("router-link"), b = x("BaseFormatMoney"), w = x("BaseDropdownItem"), E = x("BaseDropdown"), k = x("BaseTable"); return _(), a("div", null, [ - c(Bi, { - count: w.value.length, - statuses: e.statuses, - busy: k.value, - onStatus: fe, - onDelete: pe, - onClear: ie, - onSelectPage: re + c(ua, { + count: A.value.length, + statuses: t.statuses, + busy: j.value, + invoicing: R.value, + "can-invoice": z.value, + onStatus: Se, + onDelete: Ce, + onInvoice: be, + onClear: ce, + onSelectPage: se }, null, 8, [ "count", "statuses", - "busy" + "busy", + "invoicing", + "can-invoice" ]), - O(c(u, { - title: C(m)("tasks_projects.tasks.empty_title"), - description: C(m)("tasks_projects.tasks.empty_description") + O(c(m, { + title: C(g)("tasks_projects.tasks.empty_title"), + description: C(g)("tasks_projects.tasks.empty_description") }, { - actions: D(() => [c(l, { + actions: D(() => [c(d, { variant: "primary", - onClick: ae + onClick: le }, { - left: D((e) => [c(i, { + left: D((e) => [c(u, { name: "PlusIcon", class: f(e.class) }, null, 8, ["class"])]), - default: D(() => [s(" " + S(C(m)("tasks_projects.tasks.new_task")), 1)]), + default: D(() => [s(" " + S(C(g)("tasks_projects.tasks.new_task")), 1)]), _: 1 })]), - default: D(() => [c(i, { + default: D(() => [c(u, { name: "ClipboardDocumentListIcon", class: "mt-5 mb-4 h-16 w-16 text-subtle" })]), _: 1 - }, 8, ["title", "description"]), [[T, I.value]]), - O(o("div", ko, [c(E, { + }, 8, ["title", "description"]), [[T, te.value]]), + O(o("div", go, [c(k, { ref_key: "tableRef", - ref: h, - data: ee, - columns: L.value, + ref: v, + data: re, + columns: ne.value, class: "mt-3" }, { - "cell-select": D(({ row: e }) => [c(d, { - "model-value": te(e.data), + "cell-select": D(({ row: e }) => [c(h, { + "model-value": ae(e.data), "aria-label": e.data.name, - onChange: (t) => ne(e.data) + onChange: (t) => oe(e.data) }, null, 8, [ "model-value", "aria-label", "onChange" ])]), "cell-number": D(({ row: e }) => [s("#" + S(e.data.number), 1)]), - "cell-name": D(({ row: e }) => [c(g, { + "cell-name": D(({ row: e }) => [c(y, { class: "hover:text-primary-500", - to: C(Se).task(e.data.id) + to: C(W).task(e.data.id) }, { default: D(() => [s(S(e.data.name), 1)]), _: 2 - }, 1032, ["to"])]), - "cell-status": D(({ row: e }) => [o("span", Ao, [o("span", { - class: f(["mr-2 inline-block h-2.5 w-2.5 shrink-0 rounded-full", le(e.data)?.colour ? "" : "bg-line-default"]), - style: p(le(e.data)?.colour ? { backgroundColor: le(e.data)?.colour } : void 0) - }, null, 6), s(" " + S(le(e.data)?.name ?? "-"), 1)])]), - "cell-assignee": D(({ row: e }) => [o("span", { class: f(e.data.assignee_id === null ? "text-subtle" : "") }, S(B(e.data)), 3)]), - "cell-logged": D(({ row: e }) => [o("span", jo, S(ue(e.data)), 1)]), - "cell-unbilled": D(({ row: e }) => [C(Va)(e.data).unbilled_amount > 0 ? (_(), r(v, { + }, 1032, ["to"]), e.data.due_date ? (_(), a("span", { key: 0, - amount: C(Va)(e.data).unbilled_amount - }, null, 8, ["amount"])) : (_(), a("span", Mo, "-"))]), - "cell-invoiced": D(({ row: e }) => [c(Vi, { state: C(Va)(e.data).invoiced }, null, 8, ["state"])]), - "cell-timer": D(({ row: t }) => [c(Oo, { - client: e.client, - notify: e.notify, - task: t.data, - members: e.members + class: f(["mt-0.5 block text-xs font-normal", C(mt)(e.data.due_date) && !e.data.closed_at ? "font-medium text-status-red" : "text-muted"]) + }, S(C(g)("tasks_projects.tasks.columns.due_date")) + ": " + S(C(ut)(e.data.due_date)), 3)) : i("", !0)]), + "cell-status": D(({ row: e }) => [o("span", _o, [o("span", { + class: f(["mr-2 inline-block h-2.5 w-2.5 shrink-0 rounded-full", pe(e.data)?.colour ? "" : "bg-line-default"]), + style: p(pe(e.data)?.colour ? { backgroundColor: pe(e.data)?.colour } : void 0) + }, null, 6), s(" " + S(pe(e.data)?.name ?? "-"), 1)])]), + "cell-assignee": D(({ row: e }) => [o("span", { class: f(e.data.assignee_id === null ? "text-subtle" : "") }, S(me(e.data)), 3)]), + "cell-logged": D(({ row: e }) => [o("span", vo, S(he(e.data)), 1)]), + "cell-unbilled": D(({ row: e }) => [C(nt)(e.data).unbilled_amount > 0 ? (_(), r(b, { + key: 0, + amount: C(nt)(e.data).unbilled_amount + }, null, 8, ["amount"])) : (_(), a("span", yo, "-"))]), + "cell-invoiced": D(({ row: e }) => [c(da, { state: C(nt)(e.data).invoiced }, null, 8, ["state"])]), + "cell-timer": D(({ row: e }) => [c(ho, { + client: t.client, + notify: t.notify, + task: e.data, + members: t.members }, null, 8, [ "client", "notify", "task", "members" ])]), - "cell-due_date": D(({ row: e }) => [e.data.due_date ? (_(), a("span", { - key: 0, - class: f(C(be)(e.data.due_date) && !e.data.closed_at ? "font-medium text-status-red" : "") - }, S(C(ge)(e.data.due_date)), 3)) : (_(), a("span", No, "-"))]), - "cell-actions": D(({ row: e }) => [c(b, { "content-loading": N.value === e.data.id }, { - activator: D(() => [c(i, { + "cell-actions": D(({ row: t }) => [c(E, { "content-loading": I.value === t.data.id }, { + activator: D(() => [c(u, { name: "EllipsisHorizontalIcon", class: "h-5 text-muted" })]), default: D(() => [ - c(y, { onClick: (t) => oe(e.data) }, { - default: D(() => [c(i, { + c(w, { onClick: (e) => ue(t.data) }, { + default: D(() => [c(u, { name: "PencilIcon", class: "mr-3 h-5 w-5 text-subtle group-hover:text-muted" - }), s(" " + S(C(m)("tasks_projects.general.edit")), 1)]), + }), s(" " + S(C(g)("tasks_projects.general.edit")), 1)]), _: 1 }, 8, ["onClick"]), - o("div", { + z.value ? (_(), a(e, { key: 0 }, [ge(t.data) && !R.value ? (_(), r(w, { + key: 0, + onClick: (e) => ye(t.data) + }, { + default: D(() => [c(u, { + name: "BanknotesIcon", + class: "mr-3 h-5 w-5 text-subtle group-hover:text-muted" + }), s(" " + S(C(g)("tasks_projects.tasks.invoice_task")), 1)]), + _: 1 + }, 8, ["onClick"])) : (_(), a("div", { + key: 1, class: "group flex cursor-not-allowed items-center px-4 py-2 text-sm font-normal text-subtle", - title: C(m)("tasks_projects.tasks.invoice_soon") - }, [c(i, { + title: R.value ? C(g)("tasks_projects.billing.busy") : _e(t.data) + }, [c(u, { name: "BanknotesIcon", class: "mr-3 h-5 w-5 text-subtle" - }), s(" " + S(C(m)("tasks_projects.tasks.invoice_task")), 1)], 8, Po), - c(y, { onClick: (t) => de(e.data) }, { - default: D(() => [c(i, { + }), s(" " + S(C(g)("tasks_projects.tasks.invoice_task")), 1)], 8, bo))], 64)) : i("", !0), + c(w, { onClick: (e) => xe(t.data) }, { + default: D(() => [c(u, { name: "TrashIcon", class: "mr-3 h-5 w-5 text-subtle group-hover:text-muted" - }), s(" " + S(C(m)("tasks_projects.general.delete")), 1)]), + }), s(" " + S(C(g)("tasks_projects.general.delete")), 1)]), _: 1 }, 8, ["onClick"]) ]), _: 2 }, 1032, ["content-loading"])]), _: 1 - }, 8, ["columns"])], 512), [[T, !I.value]]), - c(Yi, { - show: A.value, - client: e.client, - notify: e.notify, - task: j.value, - statuses: e.statuses, - members: e.members, - projects: P.value, - defaults: M.value, - "lock-project": e.projectId !== null, - compact: j.value === null, - onClose: n[0] ||= (e) => A.value = !1, - onSaved: se, - onDeleted: ce + }, 8, ["columns"])], 512), [[T, !te.value]]), + c(ya, { + show: N.value, + client: t.client, + notify: t.notify, + task: P.value, + statuses: t.statuses, + members: t.members, + projects: L.value, + defaults: F.value, + "lock-project": t.projectId !== null, + compact: P.value === null, + onClose: l[0] ||= (e) => N.value = !1, + onSaved: de, + onDeleted: fe }, null, 8, [ "show", "client", @@ -3800,26 +3848,27 @@ var G = { ]); }; } -}), Lo = { class: "py-4" }, Ro = { class: "flex flex-wrap items-end justify-between gap-3" }, zo = /* @__PURE__ */ l({ +}), To = { class: "py-4" }, Eo = { class: "flex flex-wrap items-end justify-between gap-3" }, Do = /* @__PURE__ */ l({ __name: "ProjectTasksTab", props: { id: {}, client: { type: [Function, Object] }, notify: { type: Function }, + router: {}, project: {} }, emits: ["refresh"], setup(e, { emit: t }) { - let r = e, i = t, l = V(), u = y(null), d = y([]), p = y([]), m = y({ ...pi }), g = n(() => r.project?.id ?? Number(r.id)), v = n(() => r.project === null ? [] : [r.project]); + let r = e, i = t, l = B(), u = y(null), d = y([]), p = y([]), m = y({ ...Ri }), g = n(() => r.project?.id ?? Number(r.id)), v = n(() => r.project === null ? [] : [r.project]); h(() => void b()); async function b() { try { - d.value = await En(r.client); + d.value = await or(r.client); } catch (e) { - r.notify("error", z(e, l("tasks_projects.task_statuses.load_failed"))); + r.notify("error", H(e, l("tasks_projects.task_statuses.load_failed"))); } try { - p.value = await Sn(r.client); + p.value = await Jt(r.client); } catch { p.value = []; } @@ -3829,7 +3878,7 @@ var G = { } return (t, n) => { let r = x("BaseIcon"), i = x("BaseButton"); - return _(), a("div", Lo, [o("div", Ro, [c(Fi, { + return _(), a("div", To, [o("div", Eo, [c(oa, { modelValue: m.value, "onUpdate:modelValue": n[0] ||= (e) => m.value = e, class: "flex-1", @@ -3852,11 +3901,12 @@ var G = { }, null, 8, ["class"])]), default: D(() => [s(" " + S(C(l)("tasks_projects.tasks.new_task")), 1)]), _: 1 - })]), c(Io, { + })]), c(wo, { ref_key: "listRef", ref: u, client: e.client, notify: e.notify, + router: e.router, filters: m.value, statuses: d.value, members: p.value, @@ -3866,6 +3916,7 @@ var G = { }, null, 8, [ "client", "notify", + "router", "filters", "statuses", "members", @@ -3874,13 +3925,13 @@ var G = { ])]); }; } -}), Bo = { class: "flex w-full items-center justify-between" }, Vo = { class: "space-y-5 px-6 py-6" }, Ho = { +}), Oo = { class: "flex w-full items-center justify-between" }, ko = { class: "space-y-5 px-6 py-6" }, Ao = { key: 0, class: "rounded-md bg-alert-warning-bg px-3 py-2 text-sm text-alert-warning-text" -}, Uo = { class: "inline-flex overflow-hidden rounded-md border border-line-default" }, Wo = ["disabled", "onClick"], Go = { +}, jo = { class: "inline-flex overflow-hidden rounded-md border border-line-default" }, Mo = ["disabled", "onClick"], No = { key: 1, class: "text-sm text-muted" -}, Ko = { class: "flex items-center justify-between border-t border-line-default px-6 py-4" }, qo = { key: 1 }, Jo = { class: "flex space-x-3" }, Yo = "09:00", Xo = /* @__PURE__ */ l({ +}, Po = { class: "flex items-center justify-between border-t border-line-default px-6 py-4" }, Fo = { key: 1 }, Io = { class: "flex space-x-3" }, Lo = "09:00", Ro = /* @__PURE__ */ l({ __name: "TimeEntryModal", props: { show: { type: Boolean }, @@ -3897,11 +3948,11 @@ var G = { "deleted" ], setup(t, { emit: l }) { - let u = t, d = l, p = ["duration", "range"], m = V(), h = v({ + let u = t, d = l, p = ["duration", "range"], m = B(), h = v({ date: "", mode: "duration", duration: "", - start: Yo, + start: Lo, end: "", description: "", billable: !0 @@ -3911,7 +3962,7 @@ var G = { }, { immediate: !0 }); function N() { let e = u.entry; - w.value = {}, g.value = e === null ? u.defaultTask ?? null : null, h.date = e ? Ya(e.started_at) : u.defaultDate ?? no(/* @__PURE__ */ new Date()), h.duration = e ? qa(e.duration_minutes) : "", h.start = e?.started_at ? Xa(e.started_at) : Yo, h.end = e?.ended_at ? Xa(e.ended_at) : "", h.description = e?.description ?? "", h.billable = e ? e.billable : g.value?.billable ?? !0, h.mode = e !== null && P(e) ? "range" : "duration", h.date === "" && (h.date = u.defaultDate ?? no(/* @__PURE__ */ new Date())), e !== null && F(e.task_id); + w.value = {}, g.value = e === null ? u.defaultTask ?? null : null, h.date = e ? Ia(e.started_at) : u.defaultDate ?? Ua(/* @__PURE__ */ new Date()), h.duration = e ? Pa(e.duration_minutes) : "", h.start = e?.started_at ? La(e.started_at) : Lo, h.end = e?.ended_at ? La(e.ended_at) : "", h.description = e?.description ?? "", h.billable = e ? e.billable : g.value?.billable ?? !0, h.mode = e !== null && P(e) ? "range" : "duration", h.date === "" && (h.date = u.defaultDate ?? Ua(/* @__PURE__ */ new Date())), e !== null && F(e.task_id); } function P(e) { if (!e.started_at || !e.ended_at) return !1; @@ -3920,32 +3971,32 @@ var G = { } async function F(e) { try { - let t = await _a(u.client, e); - g.value = t, La(t); + let t = await He(u.client, e); + g.value = t, Qe(t); } catch {} } async function I(e) { try { - let t = await ga(u.client, e ?? ""); - return t.forEach(La), t; + let t = await Ve(u.client, e ?? ""); + return t.forEach(Qe), t; } catch (e) { - return u.notify("error", z(e, m("tasks_projects.time.tasks_failed"))), []; + return u.notify("error", H(e, m("tasks_projects.time.tasks_failed"))), []; } } function L(e) { - h.date = e ? _e(e) : ""; + h.date = e ? dt(e) : ""; } - function ee(e) { + function R(e) { g.value = e, e !== null && u.entry === null && (h.billable = e.billable !== !1); } - function R() { + function z() { let e = {}, t = g.value; (t === null || typeof t.id != "number") && (e.task_id = m("tasks_projects.time.task_required")), h.date === "" && (e.date = m("tasks_projects.time.date_required")); - let n = Za(h.date, h.mode === "range" ? h.start : Yo); + let n = Ra(h.date, h.mode === "range" ? h.start : Lo); n === null && (e.started_at = m("tasks_projects.time.range_invalid")); - let r = h.mode === "duration" ? Ja(h.duration) : null; + let r = h.mode === "duration" ? Fa(h.duration) : null; h.mode === "duration" && r === null && (e.duration_minutes = m("tasks_projects.time.duration_invalid")); - let i = h.mode === "range" ? Za(h.date, h.end) : null; + let i = h.mode === "range" ? Ra(h.date, h.end) : null; if (h.mode === "range" && (i === null || n === null || i <= n) && (e.ended_at = m("tasks_projects.time.range_invalid")), w.value = e, Object.keys(e).length > 0 || t === null || n === null) return null; let a = { task_id: t.id, @@ -3953,49 +4004,49 @@ var G = { description: h.description.trim() || null, billable: h.billable }; - return h.mode === "duration" && r !== null ? (a.duration_minutes = r, a.ended_at = Qa(n, r)) : a.ended_at = i, a; + return h.mode === "duration" && r !== null ? (a.duration_minutes = r, a.ended_at = za(n, r)) : a.ended_at = i, a; } - async function te() { + async function ee() { if (T.value || j.value) return; - let e = R(); + let e = z(); if (e !== null) { T.value = !0; try { - let t = u.entry, n = t ? await aa(u.client, t.id, e) : await ia(u.client, e); + let t = u.entry, n = t ? await Ae(u.client, t.id, e) : await ke(u.client, e); d("saved", n); } catch (e) { - w.value = ce(e), u.notify("error", z(e, m("tasks_projects.time.save_failed"))); + w.value = at(e), u.notify("error", H(e, m("tasks_projects.time.save_failed"))); } finally { T.value = !1; } } } - async function ne() { + async function te() { let e = u.entry; if (!(e === null || O.value || j.value) && window.confirm(m("tasks_projects.time.delete_confirm"))) { O.value = !0; try { - await oa(u.client, e.id), d("deleted", e); + await je(u.client, e.id), d("deleted", e); } catch (e) { - u.notify("error", z(e, m("tasks_projects.time.delete_failed"))); + u.notify("error", H(e, m("tasks_projects.time.delete_failed"))); } finally { O.value = !1; } } } return (n, l) => { - let u = x("BaseIcon"), v = x("BaseInput"), y = x("BaseMultiselect"), E = x("BaseInputGroup"), N = x("BaseDatePicker"), P = x("BaseInputGrid"), F = x("BaseTextarea"), R = x("BaseSwitch"), re = x("BaseButton"), ie = x("BaseModal"); - return _(), r(ie, { + let u = x("BaseIcon"), v = x("BaseInput"), y = x("BaseMultiselect"), E = x("BaseInputGroup"), N = x("BaseDatePicker"), P = x("BaseInputGrid"), F = x("BaseTextarea"), z = x("BaseSwitch"), B = x("BaseButton"), ne = x("BaseModal"); + return _(), r(ne, { show: t.show, onClose: l[8] ||= (e) => d("close") }, { - header: D(() => [o("div", Bo, [o("span", null, S(M.value), 1), c(u, { + header: D(() => [o("div", Oo, [o("span", null, S(M.value), 1), c(u, { name: "XMarkIcon", class: "h-6 w-6 cursor-pointer text-subtle hover:text-body", onClick: l[0] ||= (e) => d("close") })])]), - default: D(() => [o("form", { onSubmit: A(te, ["prevent"]) }, [o("div", Vo, [ - j.value ? (_(), a("p", Ho, S(C(m)("tasks_projects.time.stamped_notice")), 1)) : i("", !0), + default: D(() => [o("form", { onSubmit: A(ee, ["prevent"]) }, [o("div", ko, [ + j.value ? (_(), a("p", Ao, S(C(m)("tasks_projects.time.stamped_notice")), 1)) : i("", !0), c(E, { label: C(m)("tasks_projects.time.fields.task"), error: w.value.task_id, @@ -4023,7 +4074,7 @@ var G = { searchable: "", "preserve-search": "", "resolve-on-load": "", - "onUpdate:modelValue": l[1] ||= (e) => ee(e) + "onUpdate:modelValue": l[1] ||= (e) => R(e) }, null, 8, [ "model-value", "disabled", @@ -4051,13 +4102,13 @@ var G = { ])]), _: 1 }, 8, ["label", "error"]), c(E, { label: C(m)("tasks_projects.time.fields.mode") }, { - default: D(() => [o("div", Uo, [(_(), a(e, null, b(p, (e) => o("button", { + default: D(() => [o("div", jo, [(_(), a(e, null, b(p, (e) => o("button", { key: e, type: "button", class: f(["px-3 py-2 text-sm", h.mode === e ? "bg-primary-500 text-white" : "bg-surface text-body hover:bg-hover"]), disabled: j.value, onClick: (t) => h.mode = e - }, S(C(m)(`tasks_projects.time.mode.${e}`)), 11, Wo)), 64))])]), + }, S(C(m)(`tasks_projects.time.mode.${e}`)), 11, Mo)), 64))])]), _: 1 }, 8, ["label"])]), _: 1 @@ -4146,7 +4197,7 @@ var G = { label: C(m)("tasks_projects.time.fields.billable"), error: w.value.billable }, { - default: D(() => [j.value ? (_(), a("span", Go, S(h.billable ? C(m)("tasks_projects.time.billable") : C(m)("tasks_projects.time.non_billable")), 1)) : (_(), r(R, { + default: D(() => [j.value ? (_(), a("span", No, S(h.billable ? C(m)("tasks_projects.time.billable") : C(m)("tasks_projects.time.non_billable")), 1)) : (_(), r(z, { key: 0, modelValue: h.billable, "onUpdate:modelValue": l[6] ||= (e) => h.billable = e, @@ -4154,25 +4205,25 @@ var G = { }, null, 8, ["modelValue"]))]), _: 1 }, 8, ["label", "error"]) - ]), o("div", Ko, [k.value && !j.value ? (_(), r(re, { + ]), o("div", Po, [k.value && !j.value ? (_(), r(B, { key: 0, type: "button", variant: "danger", size: "sm", loading: O.value, disabled: O.value, - onClick: ne + onClick: te }, { default: D(() => [s(S(C(m)("tasks_projects.general.delete")), 1)]), _: 1 - }, 8, ["loading", "disabled"])) : (_(), a("span", qo)), o("div", Jo, [c(re, { + }, 8, ["loading", "disabled"])) : (_(), a("span", Fo)), o("div", Io, [c(B, { type: "button", variant: "primary-outline", onClick: l[7] ||= (e) => d("close") }, { default: D(() => [s(S(j.value ? C(m)("tasks_projects.timer.close") : C(m)("tasks_projects.general.cancel")), 1)]), _: 1 - }), j.value ? i("", !0) : (_(), r(re, { + }), j.value ? i("", !0) : (_(), r(B, { key: 0, type: "submit", variant: "primary", @@ -4186,16 +4237,16 @@ var G = { }, 8, ["show"]); }; } -}), Zo = { class: "py-4" }, Qo = { class: "flex justify-end" }, $o = { class: "relative mt-3 table-container" }, es = { class: "font-medium text-heading" }, ts = { +}), zo = { class: "py-4" }, Bo = { class: "flex justify-end" }, Vo = { class: "relative mt-3 table-container" }, Ho = { class: "font-medium text-heading" }, Uo = { key: 0, class: "block text-xs text-muted" -}, ns = { +}, Wo = { key: 1, class: "text-subtle" -}, rs = { +}, Go = { key: 0, class: "text-xs text-primary-500" -}, is = 15, as = 100, os = /* @__PURE__ */ l({ +}, Ko = 15, qo = 100, Jo = /* @__PURE__ */ l({ __name: "ProjectTimeTab", props: { id: {}, @@ -4205,7 +4256,7 @@ var G = { }, emits: ["refresh"], setup(e, { emit: t }) { - let l = e, u = t, d = V(), p = _o(), m = y(null), g = y([]), v = y([]), b = y(!1), w = y(null), T = n(() => l.project?.id ?? Number(l.id)), O = n(() => [ + let l = e, u = t, d = B(), p = ro(), m = y(null), g = y([]), v = y([]), b = y(!1), w = y(null), T = n(() => l.project?.id ?? Number(l.id)), O = n(() => [ { key: "started_at", label: d("tasks_projects.project.time.columns.date"), @@ -4246,48 +4297,48 @@ var G = { ]); h(() => { k(); - }), E(za, () => m.value?.refresh(!0)); + }), E(et, () => m.value?.refresh(!0)); async function k() { try { - g.value = await Sn(l.client); + g.value = await Jt(l.client); } catch (e) { - l.notify("error", z(e, d("tasks_projects.tasks.members_failed"))); + l.notify("error", H(e, d("tasks_projects.tasks.members_failed"))); } try { - let e = await Dn(l.client, { + let e = await sr(l.client, { project_id: T.value, - limit: as + limit: qo }); v.value = e.data ?? []; } catch (e) { - l.notify("error", z(e, d("tasks_projects.tasks.load_failed"))); + l.notify("error", H(e, d("tasks_projects.tasks.load_failed"))); } } async function A({ page: e }) { let t = { page: e, - limit: is, + limit: Ko, project_id: T.value }; try { - let e = await Vn(l.client, t); + let e = await xr(l.client, t); return { data: e.data ?? [], pagination: { totalPages: e.meta?.last_page ?? 1, currentPage: e.meta?.current_page ?? 1, totalCount: e.meta?.total ?? 0, - limit: e.meta?.per_page ?? is + limit: e.meta?.per_page ?? Ko } }; } catch (e) { - return l.notify("error", z(e, d("tasks_projects.project.time.load_failed"))), { + return l.notify("error", H(e, d("tasks_projects.project.time.load_failed"))), { data: [], pagination: { totalPages: 1, currentPage: 1, totalCount: 0, - limit: is + limit: Ko } }; } @@ -4299,7 +4350,7 @@ var G = { return v.value.find((t) => t.id === e)?.name ?? `#${e}`; } function N(e) { - return e.is_running ? Ka(ao(e.started_at, p.value)) : ve(e.duration_minutes); + return e.is_running ? Na(Ka(e.started_at, p.value)) : ft(e.duration_minutes); } function P() { w.value = null, b.value = !0; @@ -4309,22 +4360,22 @@ var G = { } function I() { let e = w.value ? d("tasks_projects.time.updated") : d("tasks_projects.time.created"); - b.value = !1, w.value = null, l.notify("success", e), m.value?.refresh(!0), U(), u("refresh"); + b.value = !1, w.value = null, l.notify("success", e), m.value?.refresh(!0), V(), u("refresh"); } function L() { - b.value = !1, w.value = null, l.notify("success", d("tasks_projects.time.deleted")), m.value?.refresh(!0), U(), u("refresh"); + b.value = !1, w.value = null, l.notify("success", d("tasks_projects.time.deleted")), m.value?.refresh(!0), V(), u("refresh"); } - async function ee(e) { + async function R(e) { if (window.confirm(d("tasks_projects.time.delete_confirm"))) try { - await oa(l.client, e.id), l.notify("success", d("tasks_projects.time.deleted")), m.value?.refresh(!0), U(), u("refresh"); + await je(l.client, e.id), l.notify("success", d("tasks_projects.time.deleted")), m.value?.refresh(!0), V(), u("refresh"); } catch (e) { - l.notify("error", z(e, d("tasks_projects.time.delete_failed"))); + l.notify("error", H(e, d("tasks_projects.time.delete_failed"))); } } return (t, n) => { let l = x("BaseIcon"), u = x("BaseButton"), p = x("BaseFormatMoney"), h = x("BaseDropdownItem"), g = x("BaseDropdown"), v = x("BaseTable"); - return _(), a("div", Zo, [ - o("div", Qo, [c(u, { + return _(), a("div", zo, [ + o("div", Bo, [c(u, { variant: "primary", onClick: P }, { @@ -4335,23 +4386,23 @@ var G = { default: D(() => [s(" " + S(C(d)("tasks_projects.project.time.add_entry")), 1)]), _: 1 })]), - o("div", $o, [c(v, { + o("div", Vo, [c(v, { ref_key: "tableRef", ref: m, data: A, columns: O.value }, { - "cell-started_at": D(({ row: e }) => [s(S(e.data.started_at ? C(ge)(e.data.started_at) : "-"), 1)]), + "cell-started_at": D(({ row: e }) => [s(S(e.data.started_at ? C(ut)(e.data.started_at) : "-"), 1)]), "cell-user": D(({ row: e }) => [s(S(j(e.data.user_id)), 1)]), - "cell-task": D(({ row: e }) => [o("span", es, S(M(e.data.task_id)), 1), e.data.description ? (_(), a("span", ts, S(e.data.description), 1)) : i("", !0)]), + "cell-task": D(({ row: e }) => [o("span", Ho, S(M(e.data.task_id)), 1), e.data.description ? (_(), a("span", Uo, S(e.data.description), 1)) : i("", !0)]), "cell-duration_minutes": D(({ row: e }) => [o("span", { class: f(["tabular-nums", e.data.is_running ? "font-medium text-primary-500" : ""]) }, S(N(e.data)), 3)]), "cell-billable": D(({ row: e }) => [e.data.billable ? (_(), r(l, { key: 0, name: "CheckCircleIcon", class: "h-5 w-5 text-status-green" - })) : (_(), a("span", ns, "-"))]), + })) : (_(), a("span", Wo, "-"))]), "cell-amount": D(({ row: e }) => [c(p, { amount: e.data.amount }, null, 8, ["amount"])]), - "cell-actions": D(({ row: e }) => [e.data.is_running ? (_(), a("span", rs, S(C(d)("tasks_projects.project.time.running")), 1)) : (_(), r(g, { key: 1 }, { + "cell-actions": D(({ row: e }) => [e.data.is_running ? (_(), a("span", Go, S(C(d)("tasks_projects.project.time.running")), 1)) : (_(), r(g, { key: 1 }, { activator: D(() => [c(l, { name: "EllipsisHorizontalIcon", class: "h-5 text-muted" @@ -4364,7 +4415,7 @@ var G = { _: 1 }, 8, ["onClick"]), e.data.invoice_id === null ? (_(), r(h, { key: 0, - onClick: (t) => ee(e.data) + onClick: (t) => R(e.data) }, { default: D(() => [c(l, { name: "TrashIcon", @@ -4376,7 +4427,7 @@ var G = { }, 1024))]), _: 1 }, 8, ["columns"])]), - c(Xo, { + c(Ro, { show: b.value, client: e.client, notify: e.notify, @@ -4393,65 +4444,65 @@ var G = { ]); }; } -}), ss = { - viewProject: `${H}:view-project`, - editProject: `${H}:edit-project`, - viewTask: `${H}:view-task`, - viewOwnTime: `${H}:view-own-time` +}), Yo = { + viewProject: `${U}:view-project`, + editProject: `${U}:edit-project`, + viewTask: `${U}:view-task`, + viewOwnTime: `${U}:view-own-time` }; -function cs(e) { - e.addMessages(dn), e.registerPage({ +function Xo(e) { + e.addMessages(rr), e.registerPage({ id: "projects", - module: H, + module: U, path: "projects", - component: we(e, Tr), + component: sn(e, Zr), meta: { - ability: ss.viewProject, + ability: Yo.viewProject, title: "tasks_projects.projects.title" } }), e.registerPage({ id: "project", - module: H, + module: U, path: "projects/:id", - component: we(e, pr), + component: sn(e, zr), meta: { - ability: ss.viewProject, + ability: Yo.viewProject, title: "tasks_projects.projects.title" }, children: [ { id: "overview", path: "", - component: we(e, fi), + component: sn(e, Li), meta: { - ability: ss.viewProject, + ability: Yo.viewProject, title: "tasks_projects.project.tabs.overview" } }, { id: "tasks", path: "tasks", - component: we(e, zo), + component: sn(e, Do), meta: { - ability: ss.viewTask, + ability: Yo.viewTask, title: "tasks_projects.project.tabs.tasks" } }, { id: "time", path: "time", - component: we(e, os), + component: sn(e, Jo), meta: { - ability: ss.viewOwnTime, + ability: Yo.viewOwnTime, title: "tasks_projects.project.tabs.time" } }, { id: "members", path: "members", - component: we(e, Lr), + component: sn(e, li), meta: { - ability: ss.editProject, + ability: Yo.editProject, title: "tasks_projects.project.tabs.members" } } @@ -4460,7 +4511,7 @@ function cs(e) { } //#endregion //#region resources/js/messages/reports.ts -var ls = { en: { tasks_projects: { reports: { +var Zo = { en: { tasks_projects: { reports: { title: "Reports", load_failed: "Unable to load the report.", empty_title: "Nothing logged in this range", @@ -4505,68 +4556,68 @@ var ls = { en: { tasks_projects: { reports: { amount: "Amount", unbilled: "Unbilled" } -} } } }, us = { summary: `${fn}/reports/summary` }; -async function ds(e, t) { - let { data: n } = await e.get(us.summary, { params: t }); - return fs(n?.data, t); +} } } }, Qo = { summary: `${Rt}/reports/summary` }; +async function $o(e, t) { + let { data: n } = await e.get(Qo.summary, { params: t }); + return es(n?.data, t); } -function fs(e, t) { - let n = hs(e) ? e : {}; +function es(e, t) { + let n = rs(e) ? e : {}; return { - from: vs(n.from, t.from ?? ""), - to: vs(n.to, t.to ?? ""), - totals: ms(n.totals).map(ps), - by_project: ms(n.by_project).map((e) => ({ - ...ps(e), - project_id: _s(e.project_id), - label: vs(e.label, "") + from: os(n.from, t.from ?? ""), + to: os(n.to, t.to ?? ""), + totals: ns(n.totals).map(ts), + by_project: ns(n.by_project).map((e) => ({ + ...ts(e), + project_id: as(e.project_id), + label: os(e.label, "") })), - by_member: ms(n.by_member).map((e) => ({ - ...ps(e), - user_id: _s(e.user_id), - label: vs(e.label, "") + by_member: ns(n.by_member).map((e) => ({ + ...ts(e), + user_id: as(e.user_id), + label: os(e.label, "") })), - by_customer: ms(n.by_customer).map((e) => ({ - ...ps(e), - customer_id: _s(e.customer_id) + by_customer: ns(n.by_customer).map((e) => ({ + ...ts(e), + customer_id: as(e.customer_id) })), - by_billable: ms(n.by_billable).map((e) => ({ - ...ps(e), + by_billable: ns(n.by_billable).map((e) => ({ + ...ts(e), billable: e.billable === !0 })) }; } -function ps(e) { +function ts(e) { return { - currency_id: _s(e.currency_id), - minutes: gs(e.minutes), - amount: gs(e.amount), - billable_minutes: gs(e.billable_minutes), - billable_amount: gs(e.billable_amount), - unbilled_amount: gs(e.unbilled_amount) + currency_id: as(e.currency_id), + minutes: is(e.minutes), + amount: is(e.amount), + billable_minutes: is(e.billable_minutes), + billable_amount: is(e.billable_amount), + unbilled_amount: is(e.unbilled_amount) }; } -function ms(e) { - return Array.isArray(e) ? e.filter(hs) : []; +function ns(e) { + return Array.isArray(e) ? e.filter(rs) : []; } -function hs(e) { +function rs(e) { return typeof e == "object" && !!e; } -function gs(e) { +function is(e) { return typeof e == "number" && Number.isFinite(e) ? e : 0; } -function _s(e) { +function as(e) { return typeof e == "number" && Number.isFinite(e) ? e : null; } -function vs(e, t) { +function os(e, t) { return typeof e == "string" && e.trim() !== "" ? e : t; } //#endregion //#region resources/js/components/ReportBreakdownTable.vue?vue&type=script&setup=true&lang.ts -var ys = { class: "mt-6" }, bs = { class: "text-sm font-semibold tracking-wider text-muted uppercase" }, xs = { class: "relative table-container" }, Ss = { +var ss = { class: "mt-6" }, cs = { class: "text-sm font-semibold tracking-wider text-muted uppercase" }, ls = { class: "relative table-container" }, us = { key: 0, class: "text-subtle" -}, Cs = { key: 1 }, ws = /* @__PURE__ */ l({ +}, ds = { key: 1 }, fs = /* @__PURE__ */ l({ __name: "ReportBreakdownTable", props: { title: {}, @@ -4575,7 +4626,7 @@ var ys = { class: "mt-6" }, bs = { class: "text-sm font-semibold tracking-wider showCurrency: { type: Boolean } }, setup(e) { - let t = e, i = V(), l = n(() => [ + let t = e, i = B(), l = n(() => [ { key: "label", label: t.labelHeading, @@ -4609,62 +4660,62 @@ var ys = { class: "mt-6" }, bs = { class: "text-sm font-semibold tracking-wider ]), u = n(() => t.showCurrency ? "currency" : "plain"); return (t, n) => { let i = x("BaseFormatMoney"), d = x("BaseTable"); - return _(), a("section", ys, [o("h3", bs, S(e.title), 1), o("div", xs, [(_(), r(d, { + return _(), a("section", ss, [o("h3", cs, S(e.title), 1), o("div", ls, [(_(), r(d, { key: u.value, data: e.rows, columns: l.value, class: "mt-2" }, { - "cell-currency_id": D(({ row: e }) => [e.data.currency_id === null ? (_(), a("span", Ss, "-")) : (_(), a("span", Cs, "#" + S(e.data.currency_id), 1))]), - "cell-minutes": D(({ row: e }) => [s(S(C(qa)(e.data.minutes)), 1)]), - "cell-billable_minutes": D(({ row: e }) => [s(S(C(qa)(e.data.billable_minutes)), 1)]), + "cell-currency_id": D(({ row: e }) => [e.data.currency_id === null ? (_(), a("span", us, "-")) : (_(), a("span", ds, "#" + S(e.data.currency_id), 1))]), + "cell-minutes": D(({ row: e }) => [s(S(C(Pa)(e.data.minutes)), 1)]), + "cell-billable_minutes": D(({ row: e }) => [s(S(C(Pa)(e.data.billable_minutes)), 1)]), "cell-amount": D(({ row: e }) => [c(i, { amount: e.data.amount }, null, 8, ["amount"])]), "cell-unbilled_amount": D(({ row: e }) => [c(i, { amount: e.data.unbilled_amount }, null, 8, ["amount"])]), _: 1 }, 8, ["data", "columns"]))])]); }; } -}), Ts = 3; -function Es(e, t, n = /* @__PURE__ */ new Date()) { +}), ps = 3; +function ms(e, t, n = /* @__PURE__ */ new Date()) { let r = n.getFullYear(), i = n.getMonth(); switch (e) { case "THIS_WEEK": { - let e = $a(n, t); - return Os(e, to(e, 6)); + let e = Ba(n, t); + return gs(e, Ha(e, 6)); } - case "LAST_MONTH": return Os(new Date(r, i - 1, 1), new Date(r, i, 0)); + case "LAST_MONTH": return gs(new Date(r, i - 1, 1), new Date(r, i, 0)); case "THIS_QUARTER": { - let e = Math.floor(i / Ts) * Ts; - return Os(new Date(r, e, 1), new Date(r, e + Ts, 0)); + let e = Math.floor(i / ps) * ps; + return gs(new Date(r, e, 1), new Date(r, e + ps, 0)); } - case "THIS_YEAR": return Os(new Date(r, 0, 1), new Date(r, 12, 0)); - default: return Os(new Date(r, i, 1), new Date(r, i + 1, 0)); + case "THIS_YEAR": return gs(new Date(r, 0, 1), new Date(r, 12, 0)); + default: return gs(new Date(r, i, 1), new Date(r, i + 1, 0)); } } -function Ds(e, t) { +function hs(e, t) { return t <= 0 ? 0 : Math.min(100, Math.max(0, Math.round(e / t * 100))); } -function Os(e, t) { +function gs(e, t) { return { - from: no(e), - to: no(t) + from: Ua(e), + to: Ua(t) }; } //#endregion //#region resources/js/pages/ReportsPage.vue?vue&type=script&setup=true&lang.ts -var ks = { +var _s = { key: 0, class: "mt-2 text-sm text-muted" -}, As = { class: "flex items-center justify-end space-x-5" }, js = { class: "mt-4 flex flex-wrap gap-2" }, Ms = ["onClick"], Ns = { +}, vs = { class: "flex items-center justify-end space-x-5" }, ys = { class: "mt-4 flex flex-wrap gap-2" }, bs = ["onClick"], xs = { key: 0, class: "flex justify-center py-16" -}, Ps = { +}, Ss = { key: 0, class: "text-xs font-medium tracking-wider text-muted uppercase" -}, Fs = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Is = { class: "mt-1 text-2xl font-semibold text-heading" }, Ls = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Rs = { class: "mt-1 text-2xl font-semibold text-heading" }, zs = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Bs = { class: "mt-1 text-2xl font-semibold text-heading" }, Vs = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Hs = { class: "mt-1 text-2xl font-semibold text-heading" }, Us = { class: "mt-4 rounded-xl border border-line-default bg-surface p-5" }, Ws = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Gs = { class: "mt-3 flex h-2 w-full overflow-hidden rounded-full bg-surface-tertiary" }, Ks = { class: "mt-3 flex flex-wrap gap-6 text-sm" }, qs = { class: "inline-flex items-center text-body" }, Js = { class: "ml-1 font-medium text-heading" }, Ys = { class: "ml-1 text-muted" }, Xs = { class: "inline-flex items-center text-body" }, Zs = { class: "ml-1 font-medium text-heading" }, Qs = { class: "ml-1 text-muted" }, $s = { +}, Cs = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, ws = { class: "mt-1 text-2xl font-semibold text-heading" }, Ts = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Es = { class: "mt-1 text-2xl font-semibold text-heading" }, Ds = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Os = { class: "mt-1 text-2xl font-semibold text-heading" }, ks = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, As = { class: "mt-1 text-2xl font-semibold text-heading" }, js = { class: "mt-4 rounded-xl border border-line-default bg-surface p-5" }, Ms = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Ns = { class: "mt-3 flex h-2 w-full overflow-hidden rounded-full bg-surface-tertiary" }, Ps = { class: "mt-3 flex flex-wrap gap-6 text-sm" }, Fs = { class: "inline-flex items-center text-body" }, Is = { class: "ml-1 font-medium text-heading" }, Ls = { class: "ml-1 text-muted" }, Rs = { class: "inline-flex items-center text-body" }, zs = { class: "ml-1 font-medium text-heading" }, Bs = { class: "ml-1 text-muted" }, Vs = { key: 1, class: "mt-2 text-sm text-subtle" -}, ec = "THIS_MONTH", tc = /* @__PURE__ */ l({ +}, Hs = "THIS_MONTH", Us = /* @__PURE__ */ l({ __name: "ReportsPage", props: { client: { type: [Function, Object] }, @@ -4672,7 +4723,7 @@ var ks = { router: {} }, setup(t) { - let l = t, u = V(), d = y(null), m = y([]), g = y(!0), v = y(ec), w = y(""), T = y(""), E = n(() => [ + let l = t, u = B(), d = y(null), m = y([]), g = y(!0), v = y(Hs), w = y(""), T = y(""), E = n(() => [ { id: "THIS_WEEK", label: u("tasks_projects.reports.range.this_week") @@ -4704,90 +4755,104 @@ var ks = { }))), M = n(() => (d.value?.by_member ?? []).map((e) => ({ ...e, id: `${e.user_id ?? "none"}-${e.currency_id ?? "base"}`, - label: ae(e) + label: ie(e) }))), N = n(() => (d.value?.by_customer ?? []).map((e) => ({ ...e, id: `${e.customer_id ?? "none"}-${e.currency_id ?? "base"}`, - label: e.customer_id === null ? u("tasks_projects.reports.tables.no_customer") : Zn(e.customer_id) - }))), P = n(() => oe(!0)), F = n(() => oe(!1)), I = n(() => P.value + F.value), L = n(() => Ds(P.value, I.value)); + label: e.customer_id === null ? u("tasks_projects.reports.tables.no_customer") : $t(e.customer_id) + }))), P = n(() => ae(!0)), F = n(() => ae(!1)), I = n(() => P.value + F.value), L = n(() => hs(P.value, I.value)); h(() => { - ee(ec), ie(); + R(Hs), re(); }); - function ee(e) { + function R(e) { if (v.value = e, e !== "CUSTOM") { - let t = Es(e, xa.settings.week_start); + let t = ms(e, xa.settings.week_start); w.value = t.from, T.value = t.to; } - ne(); + te(); } - function R(e) { - w.value = e ? _e(e) : "", v.value = "CUSTOM", ne(); + function z(e) { + w.value = e ? dt(e) : "", v.value = "CUSTOM", te(); } - function te(e) { - T.value = e ? _e(e) : "", v.value = "CUSTOM", ne(); + function ee(e) { + T.value = e ? dt(e) : "", v.value = "CUSTOM", te(); } - async function ne() { + async function te() { g.value = !0; try { - let e = await ds(l.client, re()); - d.value = e, e.by_customer.some((e) => e.customer_id !== null) && Qn(l.client); + let e = await $o(l.client, ne()); + d.value = e, e.by_customer.some((e) => e.customer_id !== null) && en(l.client); } catch (e) { - d.value = null, l.notify("error", z(e, u("tasks_projects.reports.load_failed"))); + d.value = null, l.notify("error", H(e, u("tasks_projects.reports.load_failed"))); } finally { g.value = !1; } } - function re() { + function ne() { let e = {}; return w.value !== "" && (e.from = w.value), T.value !== "" && (e.to = T.value), e; } - async function ie() { + async function re() { try { - m.value = await Sn(l.client); + m.value = await Jt(l.client); } catch {} } - function ae(e) { + function ie(e) { let t = m.value.find((t) => t.id === e.user_id)?.name ?? ""; return t === "" ? e.label === "" ? e.user_id === null ? u("tasks_projects.reports.tables.unknown_member") : `#${e.user_id}` : e.label : t; } - function oe(e) { + function ae(e) { return (d.value?.by_billable ?? []).filter((t) => t.billable === e).reduce((e, t) => e + t.minutes, 0); } - function se(e) { + function oe(e) { return e === null ? u("tasks_projects.reports.summary.base_currency") : u("tasks_projects.reports.summary.currency", { id: e }); } - function ce(e) { + function se(e) { return v.value === e.id ? "border-primary-500 bg-primary-50 text-primary-500" : "border-line-default bg-surface text-muted hover:text-heading"; } - function le() { - ee(ec); + function ce() { + R(Hs); } return (t, n) => { - let l = x("BaseBreadcrumbItem"), m = x("BaseBreadcrumb"), h = x("BaseIcon"), v = x("BaseButton"), y = x("router-link"), ne = x("BasePageHeader"), re = x("BaseDatePicker"), ie = x("BaseInputGroup"), ae = x("BaseFilterWrapper"), oe = x("BaseSpinner"), z = x("BaseEmptyPlaceholder"), B = x("BaseFormatMoney"), ue = x("BasePage"); + let l = x("BaseBreadcrumbItem"), m = x("BaseBreadcrumb"), h = x("BaseIcon"), v = x("BaseButton"), y = x("router-link"), B = x("BasePageHeader"), te = x("BaseDatePicker"), ne = x("BaseInputGroup"), re = x("BaseFilterWrapper"), ie = x("BaseSpinner"), ae = x("BaseEmptyPlaceholder"), le = x("BaseFormatMoney"), ue = x("BasePage"); return _(), r(ue, null, { default: D(() => [ - c(ne, { title: C(u)("tasks_projects.reports.title") }, { - actions: D(() => [o("div", As, [c(y, { to: C(Se).tasks }, { - default: D(() => [c(v, { variant: "white" }, { - left: D((e) => [c(h, { - name: "ClipboardDocumentListIcon", - class: f(e.class) - }, null, 8, ["class"])]), - default: D(() => [s(" " + S(C(u)("tasks_projects.tasks.title")), 1)]), + c(B, { title: C(u)("tasks_projects.reports.title") }, { + actions: D(() => [o("div", vs, [ + c(y, { to: C(W).tasks }, { + default: D(() => [c(v, { variant: "white" }, { + left: D((e) => [c(h, { + name: "ClipboardDocumentListIcon", + class: f(e.class) + }, null, 8, ["class"])]), + default: D(() => [s(" " + S(C(u)("tasks_projects.tasks.title")), 1)]), + _: 1 + })]), _: 1 - })]), - _: 1 - }, 8, ["to"]), c(y, { to: C(Se).projects }, { - default: D(() => [c(v, { variant: "white" }, { - left: D((e) => [c(h, { - name: "FolderIcon", - class: f(e.class) - }, null, 8, ["class"])]), - default: D(() => [s(" " + S(C(u)("tasks_projects.projects.title")), 1)]), + }, 8, ["to"]), + c(y, { to: C(W).projects }, { + default: D(() => [c(v, { variant: "white" }, { + left: D((e) => [c(h, { + name: "FolderIcon", + class: f(e.class) + }, null, 8, ["class"])]), + default: D(() => [s(" " + S(C(u)("tasks_projects.projects.title")), 1)]), + _: 1 + })]), _: 1 - })]), - _: 1 - }, 8, ["to"])])]), + }, 8, ["to"]), + c(y, { to: C(W).billing }, { + default: D(() => [c(v, { variant: "primary-outline" }, { + left: D((e) => [c(h, { + name: "BanknotesIcon", + class: f(e.class) + }, null, 8, ["class"])]), + default: D(() => [s(" " + S(C(u)("tasks_projects.billing.title")), 1)]), + _: 1 + })]), + _: 1 + }, 8, ["to"]) + ])]), default: D(() => [c(m, null, { default: D(() => [ c(l, { @@ -4796,7 +4861,7 @@ var ks = { }, null, 8, ["title"]), c(l, { title: C(u)("tasks_projects.tasks.title"), - to: C(Se).tasks + to: C(W).tasks }, null, 8, ["title", "to"]), c(l, { title: C(u)("tasks_projects.reports.title"), @@ -4805,67 +4870,67 @@ var ks = { }, null, 8, ["title"]) ]), _: 1 - }), d.value ? (_(), a("p", ks, S(C(ge)(d.value.from)) + " – " + S(C(ge)(d.value.to)), 1)) : i("", !0)]), + }), d.value ? (_(), a("p", _s, S(C(ut)(d.value.from)) + " – " + S(C(ut)(d.value.to)), 1)) : i("", !0)]), _: 1 }, 8, ["title"]), - o("div", js, [(_(!0), a(e, null, b(E.value, (e) => (_(), a("button", { + o("div", ys, [(_(!0), a(e, null, b(E.value, (e) => (_(), a("button", { key: e.id, type: "button", - class: f(["rounded-md border px-3 py-1.5 text-sm font-medium", ce(e)]), - onClick: (t) => ee(e.id) - }, S(e.label), 11, Ms))), 128))]), - c(ae, { + class: f(["rounded-md border px-3 py-1.5 text-sm font-medium", se(e)]), + onClick: (t) => R(e.id) + }, S(e.label), 11, bs))), 128))]), + c(re, { show: !0, "row-on-xl": "", class: "mt-3", - onClear: le + onClear: ce }, { - default: D(() => [c(ie, { + default: D(() => [c(ne, { label: C(u)("tasks_projects.reports.range.from"), class: "mt-2 flex-1" }, { - default: D(() => [c(re, { + default: D(() => [c(te, { "model-value": w.value, - "onUpdate:modelValue": R + "onUpdate:modelValue": z }, null, 8, ["model-value"])]), _: 1 - }, 8, ["label"]), c(ie, { + }, 8, ["label"]), c(ne, { label: C(u)("tasks_projects.reports.range.to"), class: "mt-2 flex-1" }, { - default: D(() => [c(re, { + default: D(() => [c(te, { "model-value": T.value, - "onUpdate:modelValue": te + "onUpdate:modelValue": ee }, null, 8, ["model-value"])]), _: 1 }, 8, ["label"])]), _: 1 }), - g.value && d.value === null ? (_(), a("div", Ns, [c(oe, { class: "h-8 w-8 text-primary-500" })])) : A.value ? (_(), a(e, { key: 2 }, [ + g.value && d.value === null ? (_(), a("div", xs, [c(ie, { class: "h-8 w-8 text-primary-500" })])) : A.value ? (_(), a(e, { key: 2 }, [ (_(!0), a(e, null, b(O.value, (e) => (_(), a("div", { key: e.currency_id ?? "base", class: "mt-4 rounded-xl border border-line-default bg-surface p-5" - }, [k.value ? (_(), a("p", Ps, S(se(e.currency_id)), 1)) : i("", !0), o("div", { class: f(["grid grid-cols-2 gap-4 sm:grid-cols-4", k.value ? "mt-3" : ""]) }, [ - o("div", null, [o("p", Fs, S(C(u)("tasks_projects.reports.summary.logged")), 1), o("p", Is, S(C(qa)(e.minutes)), 1)]), - o("div", null, [o("p", Ls, S(C(u)("tasks_projects.reports.summary.billable")), 1), o("p", Rs, S(C(qa)(e.billable_minutes)), 1)]), - o("div", null, [o("p", zs, S(C(u)("tasks_projects.reports.summary.amount")), 1), o("p", Bs, [c(B, { amount: e.amount }, null, 8, ["amount"])])]), - o("div", null, [o("p", Vs, S(C(u)("tasks_projects.reports.summary.unbilled")), 1), o("p", Hs, [c(B, { amount: e.unbilled_amount }, null, 8, ["amount"])])]) + }, [k.value ? (_(), a("p", Ss, S(oe(e.currency_id)), 1)) : i("", !0), o("div", { class: f(["grid grid-cols-2 gap-4 sm:grid-cols-4", k.value ? "mt-3" : ""]) }, [ + o("div", null, [o("p", Cs, S(C(u)("tasks_projects.reports.summary.logged")), 1), o("p", ws, S(C(Pa)(e.minutes)), 1)]), + o("div", null, [o("p", Ts, S(C(u)("tasks_projects.reports.summary.billable")), 1), o("p", Es, S(C(Pa)(e.billable_minutes)), 1)]), + o("div", null, [o("p", Ds, S(C(u)("tasks_projects.reports.summary.amount")), 1), o("p", Os, [c(le, { amount: e.amount }, null, 8, ["amount"])])]), + o("div", null, [o("p", ks, S(C(u)("tasks_projects.reports.summary.unbilled")), 1), o("p", As, [c(le, { amount: e.unbilled_amount }, null, 8, ["amount"])])]) ], 2)]))), 128)), - o("section", Us, [o("p", Ws, S(C(u)("tasks_projects.reports.split.title")), 1), I.value > 0 ? (_(), a(e, { key: 0 }, [o("div", Gs, [o("div", { + o("section", js, [o("p", Ms, S(C(u)("tasks_projects.reports.split.title")), 1), I.value > 0 ? (_(), a(e, { key: 0 }, [o("div", Ns, [o("div", { class: "h-2 bg-primary-500", style: p({ width: `${L.value}%` }) - }, null, 4)]), o("div", Ks, [o("span", qs, [ + }, null, 4)]), o("div", Ps, [o("span", Fs, [ n[0] ||= o("span", { class: "mr-2 inline-block h-2.5 w-2.5 rounded-full bg-primary-500" }, null, -1), s(" " + S(C(u)("tasks_projects.reports.split.billable")) + ": ", 1), - o("span", Js, S(C(qa)(P.value)), 1), - o("span", Ys, "(" + S(L.value) + "%)", 1) - ]), o("span", Xs, [ + o("span", Is, S(C(Pa)(P.value)), 1), + o("span", Ls, "(" + S(L.value) + "%)", 1) + ]), o("span", Rs, [ n[1] ||= o("span", { class: "mr-2 inline-block h-2.5 w-2.5 rounded-full bg-surface-tertiary" }, null, -1), s(" " + S(C(u)("tasks_projects.reports.split.non_billable")) + ": ", 1), - o("span", Zs, S(C(qa)(F.value)), 1), - o("span", Qs, "(" + S(100 - L.value) + "%)", 1) - ])])], 64)) : (_(), a("p", $s, S(C(u)("tasks_projects.reports.split.nothing")), 1))]), - c(ws, { + o("span", zs, S(C(Pa)(F.value)), 1), + o("span", Bs, "(" + S(100 - L.value) + "%)", 1) + ])])], 64)) : (_(), a("p", Vs, S(C(u)("tasks_projects.reports.split.nothing")), 1))]), + c(fs, { title: C(u)("tasks_projects.reports.tables.by_project"), "label-heading": C(u)("tasks_projects.reports.tables.project"), rows: j.value, @@ -4876,7 +4941,7 @@ var ks = { "rows", "show-currency" ]), - c(ws, { + c(fs, { title: C(u)("tasks_projects.reports.tables.by_member"), "label-heading": C(u)("tasks_projects.reports.tables.member"), rows: M.value, @@ -4887,7 +4952,7 @@ var ks = { "rows", "show-currency" ]), - c(ws, { + c(fs, { title: C(u)("tasks_projects.reports.tables.by_customer"), "label-heading": C(u)("tasks_projects.reports.tables.customer"), rows: N.value, @@ -4898,7 +4963,7 @@ var ks = { "rows", "show-currency" ]) - ], 64)) : (_(), r(z, { + ], 64)) : (_(), r(ae, { key: 1, title: C(u)("tasks_projects.reports.empty_title"), description: C(u)("tasks_projects.reports.empty_description") @@ -4914,24 +4979,24 @@ var ks = { }); }; } -}), nc = "tasks-projects"; -function rc(e) { - e.addMessages(ls), e.registerPage({ +}), Ws = "tasks-projects"; +function Gs(e) { + e.addMessages(Zo), e.registerPage({ id: "reports", - module: nc, + module: Ws, path: "reports", - component: we(e, tc), + component: sn(e, Us), meta: { - ability: `${nc}:view-own-time`, + ability: `${Ws}:view-own-time`, title: "tasks_projects.reports.title" } }), e.on("company:changing", () => { - $n(); + tn(); }); } //#endregion //#region resources/js/messages/tasks.ts -var ic = { en: { tasks_projects: { +var Ks = { en: { tasks_projects: { board: { title: "Board", load_failed: "Unable to load the board.", @@ -4959,7 +5024,8 @@ var ic = { en: { tasks_projects: { invoiced: "Invoiced", uninvoiced: "Unbilled", invoice_task: "Invoice task", - invoice_soon: "Coming with invoicing", + already_invoiced: "This task is already on an invoice.", + nothing_to_invoice: "No unbilled billable time on this task.", locked: "This task is on an invoice and cannot be changed.", views: { list: "List", @@ -5080,19 +5146,19 @@ var ic = { en: { tasks_projects: { load_failed: "Unable to load the task statuses.", none: "No board columns yet." } -} } }, ac = { class: "mt-6 rounded-xl border border-line-default bg-surface" }, oc = { class: "flex items-center justify-between border-b border-line-light px-5 py-3" }, sc = { class: "text-sm font-semibold text-heading" }, cc = ["title"], lc = { class: "overflow-x-auto" }, uc = { class: "min-w-full text-sm" }, dc = { class: "bg-surface-secondary text-xs tracking-wide text-muted uppercase" }, fc = { class: "px-4 py-2 text-left font-medium" }, pc = { class: "px-4 py-2 text-left font-medium" }, mc = { class: "px-4 py-2 text-left font-medium" }, hc = { class: "px-4 py-2 text-left font-medium" }, gc = { class: "px-4 py-2 text-left font-medium" }, _c = { class: "px-4 py-2 text-left font-medium" }, vc = { class: "px-4 py-2 text-left font-medium" }, yc = { class: "px-4 py-2 text-left font-medium" }, bc = { class: "px-4 py-2 text-right font-medium" }, xc = ["onClick"], Sc = { class: "px-4 py-2.5 whitespace-nowrap" }, Cc = { class: "px-4 py-2.5 whitespace-nowrap tabular-nums" }, wc = { class: "px-4 py-2.5 whitespace-nowrap" }, Tc = { +} } }, qs = { class: "mt-6 rounded-xl border border-line-default bg-surface" }, Js = { class: "flex items-center justify-between border-b border-line-light px-5 py-3" }, Ys = { class: "text-sm font-semibold text-heading" }, Xs = ["title"], Zs = { class: "overflow-x-auto" }, Qs = { class: "min-w-full text-sm" }, $s = { class: "bg-surface-secondary text-xs tracking-wide text-muted uppercase" }, ec = { class: "px-4 py-2 text-left font-medium" }, tc = { class: "px-4 py-2 text-left font-medium" }, nc = { class: "px-4 py-2 text-left font-medium" }, rc = { class: "px-4 py-2 text-left font-medium" }, ic = { class: "px-4 py-2 text-left font-medium" }, ac = { class: "px-4 py-2 text-left font-medium" }, oc = { class: "px-4 py-2 text-left font-medium" }, sc = { class: "px-4 py-2 text-left font-medium" }, cc = { class: "px-4 py-2 text-right font-medium" }, lc = ["onClick"], uc = { class: "px-4 py-2.5 whitespace-nowrap" }, dc = { class: "px-4 py-2.5 whitespace-nowrap tabular-nums" }, fc = { class: "px-4 py-2.5 whitespace-nowrap" }, pc = { key: 0, class: "text-primary-500" -}, Ec = { key: 1 }, Dc = { class: "px-4 py-2.5 whitespace-nowrap tabular-nums" }, Oc = { class: "px-4 py-2.5 whitespace-nowrap tabular-nums" }, kc = { class: "max-w-64 truncate px-4 py-2.5" }, Ac = { class: "px-4 py-2.5" }, jc = { +}, mc = { key: 1 }, hc = { class: "px-4 py-2.5 whitespace-nowrap tabular-nums" }, gc = { class: "px-4 py-2.5 whitespace-nowrap tabular-nums" }, _c = { class: "max-w-64 truncate px-4 py-2.5" }, vc = { class: "px-4 py-2.5" }, yc = { key: 1, class: "text-subtle" -}, Mc = { class: "px-4 py-2.5 whitespace-nowrap" }, Nc = ["title"], Pc = { +}, bc = { class: "px-4 py-2.5 whitespace-nowrap" }, xc = ["title"], Sc = { key: 2, class: "text-xs text-primary-500" -}, Fc = { key: 0 }, Ic = { +}, Cc = { key: 0 }, wc = { colspan: "9", class: "px-4 py-8 text-center text-sm text-subtle" -}, Lc = /* @__PURE__ */ l({ +}, Tc = /* @__PURE__ */ l({ __name: "TimeLogGrid", props: { client: {}, @@ -5101,20 +5167,20 @@ var ic = { en: { tasks_projects: { members: { default: () => [] } }, setup(t) { - let l = t, u = V(), d = _o(), p = y([]), m = y(!1), h = y(!1), g = y(null), v = n(() => ({ + let l = t, u = B(), d = ro(), p = y([]), m = y(!1), h = y(!1), g = y(null), v = n(() => ({ id: l.task.id, name: l.task.name, number: l.task.number, project_id: l.task.project_id, billable: l.task.billable - })), w = n(() => G.isRunningOn(l.task.id)); - E(() => l.task.id, () => void T(), { immediate: !0 }), E(za, () => void T()); + })), w = n(() => K.isRunningOn(l.task.id)); + E(() => l.task.id, () => void T(), { immediate: !0 }), E(et, () => void T()); async function T() { m.value = !0; try { - p.value = await Pn(l.client, l.task.id); + p.value = await mr(l.client, l.task.id); } catch (e) { - p.value = [], l.notify("error", z(e, u("tasks_projects.tasks.time_log.load_failed"))); + p.value = [], l.notify("error", H(e, u("tasks_projects.tasks.time_log.load_failed"))); } finally { m.value = !1; } @@ -5126,7 +5192,7 @@ var ic = { en: { tasks_projects: { return l.members.find((t) => t.id === e)?.name ?? `#${e}`; } function j(e) { - return e.is_running ? Ka(ao(e.started_at, d.value)) : qa(e.duration_minutes); + return e.is_running ? Na(Ka(e.started_at, d.value)) : Pa(e.duration_minutes); } function M() { w.value || (g.value = null, h.value = !0); @@ -5136,10 +5202,10 @@ var ic = { en: { tasks_projects: { } function P() { let e = g.value ? u("tasks_projects.time.updated") : u("tasks_projects.time.created"); - h.value = !1, g.value = null, l.notify("success", e), U(); + h.value = !1, g.value = null, l.notify("success", e), V(); } function F() { - h.value = !1, g.value = null, l.notify("success", u("tasks_projects.time.deleted")), U(); + h.value = !1, g.value = null, l.notify("success", u("tasks_projects.time.deleted")), V(); } async function I(e) { if (O(e)) { @@ -5147,15 +5213,15 @@ var ic = { en: { tasks_projects: { return; } if (window.confirm(u("tasks_projects.time.delete_confirm"))) try { - await oa(l.client, e.id), l.notify("success", u("tasks_projects.time.deleted")), U(); + await je(l.client, e.id), l.notify("success", u("tasks_projects.time.deleted")), V(); } catch (e) { - l.notify("error", z(e, u("tasks_projects.time.delete_failed"))); + l.notify("error", H(e, u("tasks_projects.time.delete_failed"))); } } return (n, l) => { let d = x("BaseSpinner"), y = x("BaseIcon"), T = x("BaseButton"), E = x("BaseDropdownItem"), L = x("BaseDropdown"); - return _(), a("section", ac, [ - o("header", oc, [o("h2", sc, [s(S(C(u)("tasks_projects.tasks.time_log.title")) + " ", 1), m.value ? (_(), r(d, { + return _(), a("section", qs, [ + o("header", Js, [o("h2", Ys, [s(S(C(u)("tasks_projects.tasks.time_log.title")) + " ", 1), m.value ? (_(), r(d, { key: 0, class: "ml-2 inline-block h-4 w-4 text-primary-500" })) : i("", !0)]), o("span", { title: w.value ? C(u)("tasks_projects.tasks.time_log.add_disabled") : void 0 }, [c(T, { @@ -5170,34 +5236,34 @@ var ic = { en: { tasks_projects: { }, null, 8, ["class"])]), default: D(() => [s(" " + S(C(u)("tasks_projects.tasks.time_log.add_item")), 1)]), _: 1 - }, 8, ["disabled"])], 8, cc)]), - o("div", lc, [o("table", uc, [o("thead", dc, [o("tr", null, [ - o("th", fc, S(C(u)("tasks_projects.tasks.time_log.columns.start_date")), 1), - o("th", pc, S(C(u)("tasks_projects.tasks.time_log.columns.start_time")), 1), - o("th", mc, S(C(u)("tasks_projects.tasks.time_log.columns.end_date")), 1), - o("th", hc, S(C(u)("tasks_projects.tasks.time_log.columns.end_time")), 1), - o("th", gc, S(C(u)("tasks_projects.tasks.time_log.columns.duration")), 1), - o("th", _c, S(C(u)("tasks_projects.tasks.time_log.columns.description")), 1), - o("th", vc, S(C(u)("tasks_projects.tasks.time_log.columns.billable")), 1), - o("th", yc, S(C(u)("tasks_projects.tasks.time_log.columns.member")), 1), - o("th", bc, S(C(u)("tasks_projects.general.actions")), 1) + }, 8, ["disabled"])], 8, Xs)]), + o("div", Zs, [o("table", Qs, [o("thead", $s, [o("tr", null, [ + o("th", ec, S(C(u)("tasks_projects.tasks.time_log.columns.start_date")), 1), + o("th", tc, S(C(u)("tasks_projects.tasks.time_log.columns.start_time")), 1), + o("th", nc, S(C(u)("tasks_projects.tasks.time_log.columns.end_date")), 1), + o("th", rc, S(C(u)("tasks_projects.tasks.time_log.columns.end_time")), 1), + o("th", ic, S(C(u)("tasks_projects.tasks.time_log.columns.duration")), 1), + o("th", ac, S(C(u)("tasks_projects.tasks.time_log.columns.description")), 1), + o("th", oc, S(C(u)("tasks_projects.tasks.time_log.columns.billable")), 1), + o("th", sc, S(C(u)("tasks_projects.tasks.time_log.columns.member")), 1), + o("th", cc, S(C(u)("tasks_projects.general.actions")), 1) ])]), o("tbody", null, [(_(!0), a(e, null, b(p.value, (e) => (_(), a("tr", { key: e.id, class: f(["border-t border-line-light", e.is_running ? "bg-primary-50" : "cursor-pointer hover:bg-hover"]), onClick: (t) => N(e) }, [ - o("td", Sc, S(C(ge)(C(Ya)(e.started_at)) || "-"), 1), - o("td", Cc, S(C(Xa)(e.started_at) || "-"), 1), - o("td", wc, [e.is_running ? (_(), a("span", Tc, S(C(u)("tasks_projects.tasks.time_log.running")), 1)) : (_(), a("span", Ec, S(C(ge)(C(Ya)(e.ended_at)) || "-"), 1))]), - o("td", Dc, S(e.is_running ? "-" : C(Xa)(e.ended_at) || "-"), 1), - o("td", Oc, [o("span", { class: f(e.is_running ? "font-medium text-primary-500" : "") }, S(j(e)), 3)]), - o("td", kc, S(e.description || "-"), 1), - o("td", Ac, [e.billable ? (_(), r(y, { + o("td", uc, S(C(ut)(C(Ia)(e.started_at)) || "-"), 1), + o("td", dc, S(C(La)(e.started_at) || "-"), 1), + o("td", fc, [e.is_running ? (_(), a("span", pc, S(C(u)("tasks_projects.tasks.time_log.running")), 1)) : (_(), a("span", mc, S(C(ut)(C(Ia)(e.ended_at)) || "-"), 1))]), + o("td", hc, S(e.is_running ? "-" : C(La)(e.ended_at) || "-"), 1), + o("td", gc, [o("span", { class: f(e.is_running ? "font-medium text-primary-500" : "") }, S(j(e)), 3)]), + o("td", _c, S(e.description || "-"), 1), + o("td", vc, [e.billable ? (_(), r(y, { key: 0, name: "CheckCircleIcon", class: "h-5 w-5 text-status-green" - })) : (_(), a("span", jc, "-"))]), - o("td", Mc, S(k(e.user_id)), 1), + })) : (_(), a("span", yc, "-"))]), + o("td", bc, S(k(e.user_id)), 1), o("td", { class: "px-4 py-2.5 text-right whitespace-nowrap", onClick: l[0] ||= A(() => {}, ["stop"]) @@ -5205,7 +5271,7 @@ var ic = { en: { tasks_projects: { key: 0, class: "text-xs text-muted", title: C(u)("tasks_projects.tasks.time_log.stamped_delete") - }, S(C(u)("tasks_projects.tasks.time_log.stamped")), 9, Nc)) : e.is_running ? (_(), a("span", Pc, S(C(u)("tasks_projects.tasks.time_log.running")), 1)) : (_(), r(L, { key: 1 }, { + }, S(C(u)("tasks_projects.tasks.time_log.stamped")), 9, xc)) : e.is_running ? (_(), a("span", Sc, S(C(u)("tasks_projects.tasks.time_log.running")), 1)) : (_(), r(L, { key: 1 }, { activator: D(() => [c(y, { name: "EllipsisHorizontalIcon", class: "h-5 text-muted" @@ -5225,8 +5291,8 @@ var ic = { en: { tasks_projects: { }, 8, ["onClick"])]), _: 2 }, 1024))]) - ], 10, xc))), 128)), p.value.length === 0 && !m.value ? (_(), a("tr", Fc, [o("td", Ic, S(C(u)("tasks_projects.tasks.time_log.empty")), 1)])) : i("", !0)])])]), - c(Xo, { + ], 10, lc))), 128)), p.value.length === 0 && !m.value ? (_(), a("tr", Cc, [o("td", wc, S(C(u)("tasks_projects.tasks.time_log.empty")), 1)])) : i("", !0)])])]), + c(Ro, { show: h.value, client: t.client, notify: t.notify, @@ -5246,25 +5312,25 @@ var ic = { en: { tasks_projects: { ]); }; } -}), Rc = { +}), Ec = { key: 0, class: "mt-2 flex flex-wrap items-center gap-3 text-sm text-muted" -}, zc = { class: "rounded-sm bg-surface-tertiary px-2 py-0.5 text-body" }, Bc = { +}, Dc = { class: "rounded-sm bg-surface-tertiary px-2 py-0.5 text-body" }, Oc = { key: 1, class: "text-subtle" -}, Vc = { +}, kc = { key: 0, class: "flex flex-wrap items-center justify-end gap-3" -}, Hc = ["title"], Uc = { +}, Ac = ["title"], jc = { key: 0, class: "flex justify-center py-16" -}, Wc = { class: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4" }, Gc = { class: "rounded-xl border border-line-default bg-surface p-5" }, Kc = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, qc = { class: "mt-2" }, Jc = { class: "mt-2 text-xs text-muted" }, Yc = { class: "text-body" }, Xc = { class: "rounded-xl border border-line-default bg-surface p-5" }, Zc = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Qc = { class: "mt-2 text-2xl font-semibold text-heading" }, $c = { class: "mt-1 text-xs text-muted" }, el = { class: "text-body" }, tl = { class: "rounded-xl border border-line-default bg-surface p-5" }, nl = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, rl = { class: "mt-2 text-2xl font-semibold text-heading" }, il = { class: "mt-1 text-xs text-muted" }, al = { class: "rounded-xl border border-line-default bg-surface p-5" }, ol = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, sl = { class: "mt-2 text-lg font-semibold text-heading" }, cl = { class: "mt-1 text-xs text-muted" }, ll = { class: "mt-4 rounded-xl border border-line-default bg-surface p-5" }, ul = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, dl = { +}, Mc = { class: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4" }, Nc = { class: "rounded-xl border border-line-default bg-surface p-5" }, Pc = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Fc = { class: "mt-2" }, Ic = { class: "mt-2 text-xs text-muted" }, Lc = { class: "text-body" }, Rc = { class: "rounded-xl border border-line-default bg-surface p-5" }, zc = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Bc = { class: "mt-2 text-2xl font-semibold text-heading" }, Vc = { class: "mt-1 text-xs text-muted" }, Hc = { class: "text-body" }, Uc = { class: "rounded-xl border border-line-default bg-surface p-5" }, Wc = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Gc = { class: "mt-2 text-2xl font-semibold text-heading" }, Kc = { class: "mt-1 text-xs text-muted" }, qc = { class: "rounded-xl border border-line-default bg-surface p-5" }, Jc = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, Yc = { class: "mt-2 text-lg font-semibold text-heading" }, Xc = { class: "mt-1 text-xs text-muted" }, Zc = { class: "mt-4 rounded-xl border border-line-default bg-surface p-5" }, Qc = { class: "text-xs font-medium tracking-wider text-muted uppercase" }, $c = { key: 0, class: "mt-2 text-sm whitespace-pre-line text-body" -}, fl = { +}, el = { key: 1, class: "mt-2 text-sm text-subtle" -}, pl = 100, ml = /* @__PURE__ */ l({ +}, tl = 100, nl = /* @__PURE__ */ l({ __name: "TaskPage", props: { id: {}, @@ -5278,51 +5344,51 @@ var ic = { en: { tasks_projects: { NORMAL: "bg-primary-50 text-primary-500", HIGH: "bg-alert-warning-bg text-alert-warning-text", URGENT: "bg-alert-error-bg text-alert-error-text" - }, d = V(), p = l.router, m = y(null), g = y([]), v = y([]), b = y([]), w = y(!0), T = y(!1), O = y(!1), k = y(!1), A = n(() => Number(l.id)), j = n(() => Va(m.value)), M = n(() => m.value?.name ?? d("tasks_projects.tasks.title")), N = n(() => g.value.map((e) => ({ + }, d = B(), p = l.router, m = y(null), g = y([]), v = y([]), b = y([]), w = y(!0), T = y(!1), O = y(!1), k = y(!1), A = n(() => Number(l.id)), j = n(() => nt(m.value)), N = n(() => m.value?.name ?? d("tasks_projects.tasks.title")), P = n(() => g.value.map((e) => ({ id: e.id, label: e.name - }))), P = n(() => b.value.map((e) => ({ + }))), F = n(() => b.value.map((e) => ({ id: e.id, label: e.name - }))), F = n(() => b.value.find((e) => e.id === m.value?.project_id)), I = n(() => { + }))), I = n(() => b.value.find((e) => e.id === m.value?.project_id)), L = n(() => { let e = m.value?.assignee_id ?? null; return e === null ? d("tasks_projects.tasks.unassigned") : v.value.find((t) => t.id === e)?.name ?? `#${e}`; - }), L = n({ - get: () => N.value.find((e) => e.id === m.value?.task_status_id) ?? null, + }), R = n({ + get: () => P.value.find((e) => e.id === m.value?.task_status_id) ?? null, set: (e) => { - e !== null && re(e); + e !== null && oe(e); } - }), ee = n(() => m.value?.priority ? d(`tasks_projects.tasks.priority.${m.value.priority.toLowerCase()}`) : null); - E(A, () => void R()), E(za, () => void R(!0)), h(() => { - R(), te(); + }), z = n(() => M.busy), ee = n(() => j.value.invoiced === "uninvoiced"), te = n(() => j.value.invoiced === "invoiced" ? d("tasks_projects.tasks.already_invoiced") : d("tasks_projects.tasks.nothing_to_invoice")), ne = n(() => m.value?.priority ? d(`tasks_projects.tasks.priority.${m.value.priority.toLowerCase()}`) : null); + E(A, () => void re()), E(et, () => void re(!0)), h(() => { + re(), ie(); }); - async function R(e = !1) { + async function re(e = !1) { if (!(!Number.isInteger(A.value) || A.value <= 0)) { w.value = !e; try { - let e = await jn(l.client, A.value); - m.value = e, La(e), e.customer_id !== null && Qn(l.client); + let e = await dr(l.client, A.value); + m.value = e, Qe(e), e.customer_id !== null && en(l.client); } catch (t) { - e || l.notify("error", z(t, d("tasks_projects.tasks.detail.not_found"))); + e || l.notify("error", H(t, d("tasks_projects.tasks.detail.not_found"))); } finally { w.value = !1; } } } - async function te() { + async function ie() { try { - g.value = await En(l.client); + g.value = await or(l.client); } catch (e) { - l.notify("error", z(e, d("tasks_projects.task_statuses.load_failed"))); + l.notify("error", H(e, d("tasks_projects.task_statuses.load_failed"))); } try { - v.value = await Sn(l.client); + v.value = await Jt(l.client); } catch { v.value = []; } try { - let e = await gn(l.client, { - limit: pl, + let e = await Ht(l.client, { + limit: tl, status: "ACTIVE", sort_by: "name" }); @@ -5331,7 +5397,7 @@ var ic = { en: { tasks_projects: { b.value = []; } } - function ne(e, t) { + function ae(e, t) { return { name: e.name, task_status_id: e.task_status_id, @@ -5347,45 +5413,54 @@ var ic = { en: { tasks_projects: { ...t }; } - async function re(e) { + async function oe(e) { let t = m.value; if (t === null || T.value || t.task_status_id === e.id) return; let n = t.task_status_id; t.task_status_id = e.id, T.value = !0; try { - m.value = await kn(l.client, t.id, ne(t, { task_status_id: e.id })), l.notify("success", d("tasks_projects.tasks.detail.status_saved", { name: e.label })), U(); + m.value = await lr(l.client, t.id, ae(t, { task_status_id: e.id })), l.notify("success", d("tasks_projects.tasks.detail.status_saved", { name: e.label })), V(); } catch (e) { - t.task_status_id = n, l.notify("error", z(e, B(e) === "task_locked" ? d("tasks_projects.tasks.locked") : d("tasks_projects.tasks.detail.status_failed"))); + t.task_status_id = n, l.notify("error", H(e, gt(e) === "task_locked" ? d("tasks_projects.tasks.locked") : d("tasks_projects.tasks.detail.status_failed"))); } finally { T.value = !1; } } - function ie() { - p.push(Se.tasks); + async function se() { + let e = m.value; + e !== null && ee.value && !z.value && await bt({ + client: l.client, + router: p, + notify: l.notify, + t: d + }, { taskIds: [e.id] }); } - function ae(e) { - k.value = !1, m.value = e, La(e), l.notify("success", d("tasks_projects.tasks.updated", { name: e.name })), U(); + function ce() { + p.push(W.tasks); + } + function le(e) { + k.value = !1, m.value = e, Qe(e), l.notify("success", d("tasks_projects.tasks.updated", { name: e.name })), V(); } - async function oe() { + async function ue() { let e = m.value; if (!(e === null || O.value) && window.confirm(d("tasks_projects.tasks.delete_confirm", { name: e.name }))) { O.value = !0; try { - await An(l.client, e.id), l.notify("success", d("tasks_projects.tasks.deleted", { name: e.name })), U(), ie(); + await ur(l.client, e.id), l.notify("success", d("tasks_projects.tasks.deleted", { name: e.name })), V(), ce(); } catch (e) { - l.notify("error", z(e, B(e) === "task_locked" ? d("tasks_projects.tasks.locked") : d("tasks_projects.tasks.delete_failed"))); + l.notify("error", H(e, gt(e) === "task_locked" ? d("tasks_projects.tasks.locked") : d("tasks_projects.tasks.delete_failed"))); } finally { O.value = !1; } } } return (n, l) => { - let p = x("BaseBreadcrumbItem"), h = x("BaseBreadcrumb"), y = x("router-link"), b = x("BaseIcon"), E = x("BaseButton"), A = x("BasePageHeader"), R = x("BaseSpinner"), te = x("BaseSelectInput"), ne = x("BaseFormatMoney"), re = x("BasePage"); - return _(), r(re, null, { + let p = x("BaseBreadcrumbItem"), h = x("BaseBreadcrumb"), y = x("router-link"), b = x("BaseIcon"), E = x("BaseButton"), A = x("BasePageHeader"), B = x("BaseSpinner"), re = x("BaseSelectInput"), ie = x("BaseFormatMoney"), ae = x("BasePage"); + return _(), r(ae, null, { default: D(() => [ - c(A, { title: M.value }, { - actions: D(() => [m.value ? (_(), a("div", Vc, [ - c(Oo, { + c(A, { title: N.value }, { + actions: D(() => [m.value ? (_(), a("div", kc, [ + c(ho, { client: t.client, notify: t.notify, task: m.value, @@ -5397,25 +5472,29 @@ var ic = { en: { tasks_projects: { "task", "members" ]), - o("span", { - title: C(d)("tasks_projects.tasks.invoice_soon"), - class: "inline-flex" + C(M).allowed ? (_(), a("span", { + key: 0, + class: "inline-flex", + title: ee.value ? void 0 : te.value }, [c(E, { variant: "white", - disabled: "" + loading: z.value, + disabled: !ee.value || z.value, + onClick: se }, { - left: D((e) => [c(b, { + left: D((e) => [z.value ? i("", !0) : (_(), r(b, { + key: 0, name: "BanknotesIcon", class: f(e.class) - }, null, 8, ["class"])]), + }, null, 8, ["class"]))]), default: D(() => [s(" " + S(C(d)("tasks_projects.tasks.invoice_task")), 1)]), _: 1 - })], 8, Hc), + }, 8, ["loading", "disabled"])], 8, Ac)) : i("", !0), c(E, { variant: "primary-outline", loading: O.value, disabled: O.value, - onClick: oe + onClick: ue }, { default: D(() => [s(S(C(d)("tasks_projects.general.delete")), 1)]), _: 1 @@ -5440,49 +5519,53 @@ var ic = { en: { tasks_projects: { }, null, 8, ["title"]), c(p, { title: C(d)("tasks_projects.tasks.title"), - to: C(Se).tasks + to: C(W).tasks }, null, 8, ["title", "to"]), c(p, { - title: m.value ? `#${m.value.number}` : M.value, + title: m.value ? `#${m.value.number}` : N.value, to: "#", active: "" }, null, 8, ["title"]) ]), _: 1 - }), m.value ? (_(), a("div", Rc, [ - o("span", zc, "#" + S(m.value.number), 1), + }), m.value ? (_(), a("div", Ec, [ + o("span", Dc, "#" + S(m.value.number), 1), m.value.project_id ? (_(), r(y, { key: 0, class: "hover:text-primary-500", - to: C(Se).project(m.value.project_id) + to: C(W).project(m.value.project_id) }, { - default: D(() => [s(S(F.value?.name ?? `#${m.value.project_id}`), 1)]), + default: D(() => [s(S(I.value?.name ?? `#${m.value.project_id}`), 1)]), _: 1 - }, 8, ["to"])) : (_(), a("span", Bc, S(C(d)("tasks_projects.tasks.no_project")), 1)), + }, 8, ["to"])) : (_(), a("span", Oc, S(C(d)("tasks_projects.tasks.no_project")), 1)), m.value.customer_id ? (_(), r(y, { key: 2, class: "hover:text-primary-500", - to: C(Se).customer(m.value.customer_id) + to: C(W).customer(m.value.customer_id) }, { - default: D(() => [s(S(C(Zn)(m.value.customer_id)), 1)]), + default: D(() => [s(S(C($t)(m.value.customer_id)), 1)]), _: 1 }, 8, ["to"])) : i("", !0), - ee.value && m.value.priority ? (_(), a("span", { + ne.value && m.value.priority ? (_(), a("span", { key: 3, class: f(["rounded-full px-2 py-0.5 text-xs font-medium", u[m.value.priority]]) - }, S(ee.value), 3)) : i("", !0), - c(Vi, { state: j.value.invoiced }, null, 8, ["state"]) + }, S(ne.value), 3)) : i("", !0), + c(da, { state: j.value.invoiced }, null, 8, ["state"]) ])) : i("", !0)]), _: 1 }, 8, ["title"]), - w.value && m.value === null ? (_(), a("div", Uc, [c(R, { class: "h-8 w-8 text-primary-500" })])) : m.value ? (_(), a(e, { key: 1 }, [ - o("div", Wc, [ - o("div", Gc, [ - o("p", Kc, S(C(d)("tasks_projects.tasks.detail.status")), 1), - o("div", qc, [c(te, { - modelValue: L.value, - "onUpdate:modelValue": l[1] ||= (e) => L.value = e, - options: N.value, + c(Lt, { + client: t.client, + notify: t.notify + }, null, 8, ["client", "notify"]), + w.value && m.value === null ? (_(), a("div", jc, [c(B, { class: "h-8 w-8 text-primary-500" })])) : m.value ? (_(), a(e, { key: 1 }, [ + o("div", Mc, [ + o("div", Nc, [ + o("p", Pc, S(C(d)("tasks_projects.tasks.detail.status")), 1), + o("div", Fc, [c(re, { + modelValue: R.value, + "onUpdate:modelValue": l[1] ||= (e) => R.value = e, + options: P.value, disabled: T.value, "label-key": "label" }, null, 8, [ @@ -5490,26 +5573,26 @@ var ic = { en: { tasks_projects: { "options", "disabled" ])]), - o("p", Jc, [s(S(C(d)("tasks_projects.tasks.detail.assignee")) + ": ", 1), o("span", Yc, S(I.value), 1)]) + o("p", Ic, [s(S(C(d)("tasks_projects.tasks.detail.assignee")) + ": ", 1), o("span", Lc, S(L.value), 1)]) ]), - o("div", Xc, [ - o("p", Zc, S(C(d)("tasks_projects.tasks.detail.logged")), 1), - o("p", Qc, S(C(ve)(j.value.logged_minutes)), 1), - o("p", $c, [s(S(C(d)("tasks_projects.tasks.detail.estimate")) + ": ", 1), o("span", el, S(m.value.estimated_minutes ? C(ve)(m.value.estimated_minutes) : C(d)("tasks_projects.tasks.detail.no_estimate")), 1)]) + o("div", Rc, [ + o("p", zc, S(C(d)("tasks_projects.tasks.detail.logged")), 1), + o("p", Bc, S(C(ft)(j.value.logged_minutes)), 1), + o("p", Vc, [s(S(C(d)("tasks_projects.tasks.detail.estimate")) + ": ", 1), o("span", Hc, S(m.value.estimated_minutes ? C(ft)(m.value.estimated_minutes) : C(d)("tasks_projects.tasks.detail.no_estimate")), 1)]) ]), - o("div", tl, [ - o("p", nl, S(C(d)("tasks_projects.tasks.detail.unbilled")), 1), - o("p", rl, [c(ne, { amount: j.value.unbilled_amount }, null, 8, ["amount"])]), - o("p", il, S(C(ve)(j.value.unbilled_minutes)), 1) + o("div", Uc, [ + o("p", Wc, S(C(d)("tasks_projects.tasks.detail.unbilled")), 1), + o("p", Gc, [c(ie, { amount: j.value.unbilled_amount }, null, 8, ["amount"])]), + o("p", Kc, S(C(ft)(j.value.unbilled_minutes)), 1) ]), - o("div", al, [ - o("p", ol, S(C(d)("tasks_projects.tasks.detail.due_date")), 1), - o("p", sl, S(m.value.due_date ? C(ge)(m.value.due_date) : "-"), 1), - o("p", cl, S(m.value.billable ? C(d)("tasks_projects.tasks.billable") : C(d)("tasks_projects.time.non_billable")), 1) + o("div", qc, [ + o("p", Jc, S(C(d)("tasks_projects.tasks.detail.due_date")), 1), + o("p", Yc, S(m.value.due_date ? C(ut)(m.value.due_date) : "-"), 1), + o("p", Xc, S(m.value.billable ? C(d)("tasks_projects.tasks.billable") : C(d)("tasks_projects.time.non_billable")), 1) ]) ]), - o("div", ll, [o("p", ul, S(C(d)("tasks_projects.tasks.detail.description")), 1), m.value.description ? (_(), a("p", dl, S(m.value.description), 1)) : (_(), a("p", fl, S(C(d)("tasks_projects.tasks.detail.no_description")), 1))]), - c(Lc, { + o("div", Zc, [o("p", Qc, S(C(d)("tasks_projects.tasks.detail.description")), 1), m.value.description ? (_(), a("p", $c, S(m.value.description), 1)) : (_(), a("p", el, S(C(d)("tasks_projects.tasks.detail.no_description")), 1))]), + c(Tc, { client: t.client, notify: t.notify, task: m.value, @@ -5521,7 +5604,7 @@ var ic = { en: { tasks_projects: { "members" ]) ], 64)) : i("", !0), - m.value ? (_(), r(Yi, { + m.value ? (_(), r(ya, { key: 2, show: k.value, client: t.client, @@ -5529,10 +5612,10 @@ var ic = { en: { tasks_projects: { task: m.value, statuses: g.value, members: v.value, - projects: P.value, + projects: F.value, onClose: l[2] ||= (e) => k.value = !1, - onSaved: ae, - onDeleted: ie + onSaved: le, + onDeleted: ce }, null, 8, [ "show", "client", @@ -5547,7 +5630,7 @@ var ic = { en: { tasks_projects: { }); }; } -}), hl = ["aria-label"], gl = ["aria-current", "onClick"], _l = { class: "max-sm:hidden" }, vl = /* @__PURE__ */ l({ +}), rl = ["aria-label"], il = ["aria-current", "onClick"], al = { class: "max-sm:hidden" }, ol = /* @__PURE__ */ l({ __name: "ViewSwitcher", props: { active: {}, @@ -5555,28 +5638,28 @@ var ic = { en: { tasks_projects: { }, emits: ["select"], setup(t, { emit: r }) { - let i = t, s = r, l = V(), u = n(() => [ + let i = t, s = r, l = B(), u = n(() => [ { id: "list", - name: Ce.list, + name: on.list, label: l("tasks_projects.tasks.views.list"), icon: "ListBulletIcon" }, { id: "board", - name: Ce.board, + name: on.board, label: l("tasks_projects.tasks.views.board"), icon: "ViewColumnsIcon" }, { id: "week", - name: Ce.week, + name: on.week, label: l("tasks_projects.tasks.views.week"), icon: "CalendarDaysIcon" } ]); function d(e) { - return i.active === e.name || e.id === "list" && i.active === Ce.tasks; + return i.active === e.name || e.id === "list" && i.active === on.tasks; } function p(e) { d(e) || s("select", { @@ -5598,10 +5681,10 @@ var ic = { en: { tasks_projects: { }, [c(r, { name: e.icon, class: "h-4 w-4" - }, null, 8, ["name"]), o("span", _l, S(e.label), 1)], 10, gl))), 128))], 8, hl); + }, null, 8, ["name"]), o("span", al, S(e.label), 1)], 10, il))), 128))], 8, rl); }; } -}), yl = { class: "flex flex-wrap items-center justify-end gap-3" }, bl = 100, xl = /* @__PURE__ */ l({ +}), sl = { class: "flex flex-wrap items-center justify-end gap-3" }, cl = 100, ll = /* @__PURE__ */ l({ __name: "TasksPage", props: { client: { type: [Function, Object] }, @@ -5609,7 +5692,7 @@ var ic = { en: { tasks_projects: { router: {} }, setup(e) { - let t = e, i = V(), a = t.router, l = y([]), u = y([]), d = y([]), p = y(!1), m = n(() => t.router.currentRoute.value), g = n(() => hi(m.value.query)), v = n(() => gi(g.value)), b = n(() => String(m.value.name ?? "")), w = n(() => d.value.map((e) => ({ + let t = e, i = B(), a = t.router, l = y([]), u = y([]), d = y([]), p = y(!1), m = n(() => t.router.currentRoute.value), g = n(() => Bi(m.value.query)), v = n(() => Vi(g.value)), b = n(() => String(m.value.name ?? "")), w = n(() => d.value.map((e) => ({ id: e.id, label: e.name }))); @@ -5617,57 +5700,57 @@ var ic = { en: { tasks_projects: { T(b.value), O(); }); function T(e) { - e === Ce.tasks && a.replace({ - name: Ce.list, + e === on.tasks && a.replace({ + name: on.list, query: v.value }); } async function O() { try { - l.value = await En(t.client); + l.value = await or(t.client); } catch (e) { - t.notify("error", z(e, i("tasks_projects.task_statuses.load_failed"))); + t.notify("error", H(e, i("tasks_projects.task_statuses.load_failed"))); } try { - u.value = await Sn(t.client); + u.value = await Jt(t.client); } catch (e) { - t.notify("error", z(e, i("tasks_projects.tasks.members_failed"))); + t.notify("error", H(e, i("tasks_projects.tasks.members_failed"))); } try { - let e = await gn(t.client, { - limit: bl, + let e = await Ht(t.client, { + limit: cl, status: "ACTIVE", sort_by: "name" }); d.value = e.data ?? []; } catch (e) { - t.notify("error", z(e, i("tasks_projects.tasks.projects_failed"))); + t.notify("error", H(e, i("tasks_projects.tasks.projects_failed"))); } } function k(e) { - yi(e, g.value) || a.replace({ - name: b.value === Ce.tasks ? Ce.list : b.value, - query: gi(e) + Wi(e, g.value) || a.replace({ + name: b.value === on.tasks ? on.list : b.value, + query: Vi(e) }); } function A(e) { a.push(e); } function j(e) { - p.value = !1, t.notify("success", i("tasks_projects.tasks.created", { name: e.name })), U(); + p.value = !1, t.notify("success", i("tasks_projects.tasks.created", { name: e.name })), V(); } return (t, n) => { let a = x("BaseBreadcrumbItem"), m = x("BaseBreadcrumb"), h = x("BaseIcon"), y = x("BaseButton"), T = x("router-link"), E = x("BasePageHeader"), O = x("router-view"), M = x("BasePage"); return _(), r(M, null, { default: D(() => [ c(E, { title: C(i)("tasks_projects.tasks.title") }, { - actions: D(() => [o("div", yl, [ - c(vl, { + actions: D(() => [o("div", sl, [ + c(ol, { active: b.value, query: v.value, onSelect: A }, null, 8, ["active", "query"]), - c(T, { to: C(Se).projects }, { + c(T, { to: C(W).projects }, { default: D(() => [c(y, { variant: "white" }, { left: D((e) => [c(h, { name: "FolderIcon", @@ -5678,7 +5761,7 @@ var ic = { en: { tasks_projects: { })]), _: 1 }, 8, ["to"]), - c(T, { to: C(Se).reports }, { + c(T, { to: C(W).reports }, { default: D(() => [c(y, { variant: "white" }, { left: D((e) => [c(h, { name: "ChartBarIcon", @@ -5714,7 +5797,11 @@ var ic = { en: { tasks_projects: { })]), _: 1 }, 8, ["title"]), - c(Fi, { + c(Lt, { + client: e.client, + notify: e.notify + }, null, 8, ["client", "notify"]), + c(oa, { "model-value": g.value, projects: d.value, members: u.value, @@ -5737,7 +5824,7 @@ var ic = { en: { tasks_projects: { "members", "projects" ]), - c(Yi, { + c(ya, { show: p.value, client: e.client, notify: e.notify, @@ -5766,24 +5853,24 @@ var ic = { en: { tasks_projects: { }); //#endregion //#region node_modules/.pnpm/sortablejs@1.15.7/node_modules/sortablejs/modular/sortable.esm.js -function Sl(e, t, n) { - return (t = kl(t)) in e ? Object.defineProperty(e, t, { +function ul(e, t, n) { + return (t = _l(t)) in e ? Object.defineProperty(e, t, { value: n, enumerable: !0, configurable: !0, writable: !0 }) : e[t] = n, e; } -function Cl() { - return Cl = Object.assign ? Object.assign.bind() : function(e) { +function dl() { + return dl = Object.assign ? Object.assign.bind() : function(e) { for (var t = 1; t < arguments.length; t++) { var n = arguments[t]; for (var r in n) ({}).hasOwnProperty.call(n, r) && (e[r] = n[r]); } return e; - }, Cl.apply(null, arguments); + }, dl.apply(null, arguments); } -function wl(e, t) { +function fl(e, t) { var n = Object.keys(e); if (Object.getOwnPropertySymbols) { var r = Object.getOwnPropertySymbols(e); @@ -5793,27 +5880,27 @@ function wl(e, t) { } return n; } -function Tl(e) { +function pl(e) { for (var t = 1; t < arguments.length; t++) { var n = arguments[t] == null ? {} : arguments[t]; - t % 2 ? wl(Object(n), !0).forEach(function(t) { - Sl(e, t, n[t]); - }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(n)) : wl(Object(n)).forEach(function(t) { + t % 2 ? fl(Object(n), !0).forEach(function(t) { + ul(e, t, n[t]); + }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(n)) : fl(Object(n)).forEach(function(t) { Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(n, t)); }); } return e; } -function El(e, t) { +function ml(e, t) { if (e == null) return {}; - var n, r, i = Dl(e, t); + var n, r, i = hl(e, t); if (Object.getOwnPropertySymbols) { var a = Object.getOwnPropertySymbols(e); for (r = 0; r < a.length; r++) n = a[r], t.indexOf(n) === -1 && {}.propertyIsEnumerable.call(e, n) && (i[n] = e[n]); } return i; } -function Dl(e, t) { +function hl(e, t) { if (e == null) return {}; var n = {}; for (var r in e) if ({}.hasOwnProperty.call(e, r)) { @@ -5822,7 +5909,7 @@ function Dl(e, t) { } return n; } -function Ol(e, t) { +function gl(e, t) { if (typeof e != "object" || !e) return e; var n = e[Symbol.toPrimitive]; if (n !== void 0) { @@ -5832,33 +5919,33 @@ function Ol(e, t) { } return (t === "string" ? String : Number)(e); } -function kl(e) { - var t = Ol(e, "string"); +function _l(e) { + var t = gl(e, "string"); return typeof t == "symbol" ? t : t + ""; } -function Al(e) { +function vl(e) { "@babel/helpers - typeof"; - return Al = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(e) { + return vl = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(e) { return typeof e; } : function(e) { return e && typeof Symbol == "function" && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e; - }, Al(e); + }, vl(e); } -var jl = "1.15.7"; -function Ml(e) { +var yl = "1.15.7"; +function bl(e) { if (typeof window < "u" && window.navigator) return !!/*@__PURE__*/ navigator.userAgent.match(e); } -var Nl = Ml(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i), Pl = Ml(/Edge/i), Fl = Ml(/firefox/i), Il = Ml(/safari/i) && !Ml(/chrome/i) && !Ml(/android/i), Ll = Ml(/iP(ad|od|hone)/i), Rl = Ml(/chrome/i) && Ml(/android/i), zl = { +var xl = bl(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i), Sl = bl(/Edge/i), Cl = bl(/firefox/i), wl = bl(/safari/i) && !bl(/chrome/i) && !bl(/android/i), Tl = bl(/iP(ad|od|hone)/i), El = bl(/chrome/i) && bl(/android/i), Dl = { capture: !1, passive: !1 }; -function K(e, t, n) { - e.addEventListener(t, n, !Nl && zl); -} function q(e, t, n) { - e.removeEventListener(t, n, !Nl && zl); + e.addEventListener(t, n, !xl && Dl); } -function Bl(e, t) { +function J(e, t, n) { + e.removeEventListener(t, n, !xl && Dl); +} +function Ol(e, t) { if (t) { if (t[0] === ">" && (t = t.substring(1)), e) try { if (e.matches) return e.matches(t); @@ -5870,41 +5957,41 @@ function Bl(e, t) { return !1; } } -function Vl(e) { +function kl(e) { return e.host && e !== document && e.host.nodeType && e.host !== e ? e.host : e.parentNode; } -function Hl(e, t, n, r) { +function Al(e, t, n, r) { if (e) { n ||= document; do { - if (t != null && (t[0] === ">" ? e.parentNode === n && Bl(e, t) : Bl(e, t)) || r && e === n) return e; + if (t != null && (t[0] === ">" ? e.parentNode === n && Ol(e, t) : Ol(e, t)) || r && e === n) return e; if (e === n) break; - } while (e = Vl(e)); + } while (e = kl(e)); } return null; } -var Ul = /\s+/g; -function Wl(e, t, n) { - e && t && (e.classList ? e.classList[n ? "add" : "remove"](t) : e.className = ((" " + e.className + " ").replace(Ul, " ").replace(" " + t + " ", " ") + (n ? " " + t : "")).replace(Ul, " ")); +var jl = /\s+/g; +function Ml(e, t, n) { + e && t && (e.classList ? e.classList[n ? "add" : "remove"](t) : e.className = ((" " + e.className + " ").replace(jl, " ").replace(" " + t + " ", " ") + (n ? " " + t : "")).replace(jl, " ")); } -function J(e, t, n) { +function Y(e, t, n) { var r = e && e.style; if (r) { if (n === void 0) return document.defaultView && document.defaultView.getComputedStyle ? n = document.defaultView.getComputedStyle(e, "") : e.currentStyle && (n = e.currentStyle), t === void 0 ? n : n[t]; !(t in r) && t.indexOf("webkit") === -1 && (t = "-webkit-" + t), r[t] = n + (typeof n == "string" ? "" : "px"); } } -function Gl(e, t) { +function Nl(e, t) { var n = ""; if (typeof e == "string") n = e; else do { - var r = J(e, "transform"); + var r = Y(e, "transform"); r && r !== "none" && (n = r + " " + n); } while (!t && (e = e.parentNode)); var i = window.DOMMatrix || window.WebKitCSSMatrix || window.CSSMatrix || window.MSCSSMatrix; return i && new i(n); } -function Kl(e, t, n) { +function Pl(e, t, n) { if (e) { var r = e.getElementsByTagName(t), i = 0, a = r.length; if (n) for (; i < a; i++) n(r[i], i); @@ -5912,21 +5999,21 @@ function Kl(e, t, n) { } return []; } -function ql() { +function Fl() { return document.scrollingElement || document.documentElement; } -function Jl(e, t, n, r, i) { +function Il(e, t, n, r, i) { if (e.getBoundingClientRect || e === window) { var a, o, s, c, l, u, d; - if (e !== window && e.parentNode && e !== ql() ? (a = e.getBoundingClientRect(), o = a.top, s = a.left, c = a.bottom, l = a.right, u = a.height, d = a.width) : (o = 0, s = 0, c = window.innerHeight, l = window.innerWidth, u = window.innerHeight, d = window.innerWidth), (t || n) && e !== window && (i ||= e.parentNode, !Nl)) do - if (i && i.getBoundingClientRect && (J(i, "transform") !== "none" || n && J(i, "position") !== "static")) { + if (e !== window && e.parentNode && e !== Fl() ? (a = e.getBoundingClientRect(), o = a.top, s = a.left, c = a.bottom, l = a.right, u = a.height, d = a.width) : (o = 0, s = 0, c = window.innerHeight, l = window.innerWidth, u = window.innerHeight, d = window.innerWidth), (t || n) && e !== window && (i ||= e.parentNode, !xl)) do + if (i && i.getBoundingClientRect && (Y(i, "transform") !== "none" || n && Y(i, "position") !== "static")) { var f = i.getBoundingClientRect(); - o -= f.top + parseInt(J(i, "border-top-width")), s -= f.left + parseInt(J(i, "border-left-width")), c = o + a.height, l = s + a.width; + o -= f.top + parseInt(Y(i, "border-top-width")), s -= f.left + parseInt(Y(i, "border-left-width")), c = o + a.height, l = s + a.width; break; } while (i = i.parentNode); if (r && e !== window) { - var p = Gl(i || e), m = p && p.a, h = p && p.d; + var p = Nl(i || e), m = p && p.a, h = p && p.d; p && (o /= h, s /= m, d /= m, u /= h, c = o + u, l = s + d); } return { @@ -5939,18 +6026,18 @@ function Jl(e, t, n, r, i) { }; } } -function Yl(e, t, n) { - for (var r = tu(e, !0), i = Jl(e)[t]; r;) { - var a = Jl(r)[n], o = void 0; +function Ll(e, t, n) { + for (var r = Ul(e, !0), i = Il(e)[t]; r;) { + var a = Il(r)[n], o = void 0; if (o = n === "top" || n === "left" ? i >= a : i <= a, !o) return r; - if (r === ql()) break; - r = tu(r, !1); + if (r === Fl()) break; + r = Ul(r, !1); } return !1; } -function Xl(e, t, n, r) { +function Rl(e, t, n, r) { for (var i = 0, a = 0, o = e.children; a < o.length;) { - if (o[a].style.display !== "none" && o[a] !== $.ghost && (r || o[a] !== $.dragged) && Hl(o[a], n.draggable, e, !1)) { + if (o[a].style.display !== "none" && o[a] !== $.ghost && (r || o[a] !== $.dragged) && Al(o[a], n.draggable, e, !1)) { if (i === t) return o[a]; i++; } @@ -5958,96 +6045,96 @@ function Xl(e, t, n, r) { } return null; } -function Zl(e, t) { - for (var n = e.lastElementChild; n && (n === $.ghost || J(n, "display") === "none" || t && !Bl(n, t));) n = n.previousElementSibling; +function zl(e, t) { + for (var n = e.lastElementChild; n && (n === $.ghost || Y(n, "display") === "none" || t && !Ol(n, t));) n = n.previousElementSibling; return n || null; } -function Ql(e, t) { +function Bl(e, t) { var n = 0; if (!e || !e.parentNode) return -1; - for (; e = e.previousElementSibling;) e.nodeName.toUpperCase() !== "TEMPLATE" && e !== $.clone && (!t || Bl(e, t)) && n++; + for (; e = e.previousElementSibling;) e.nodeName.toUpperCase() !== "TEMPLATE" && e !== $.clone && (!t || Ol(e, t)) && n++; return n; } -function $l(e) { - var t = 0, n = 0, r = ql(); +function Vl(e) { + var t = 0, n = 0, r = Fl(); if (e) do { - var i = Gl(e), a = i.a, o = i.d; + var i = Nl(e), a = i.a, o = i.d; t += e.scrollLeft * a, n += e.scrollTop * o; } while (e !== r && (e = e.parentNode)); return [t, n]; } -function eu(e, t) { +function Hl(e, t) { for (var n in e) if (e.hasOwnProperty(n)) { for (var r in t) if (t.hasOwnProperty(r) && t[r] === e[n][r]) return Number(n); } return -1; } -function tu(e, t) { - if (!e || !e.getBoundingClientRect) return ql(); +function Ul(e, t) { + if (!e || !e.getBoundingClientRect) return Fl(); var n = e, r = !1; do if (n.clientWidth < n.scrollWidth || n.clientHeight < n.scrollHeight) { - var i = J(n); + var i = Y(n); if (n.clientWidth < n.scrollWidth && (i.overflowX == "auto" || i.overflowX == "scroll") || n.clientHeight < n.scrollHeight && (i.overflowY == "auto" || i.overflowY == "scroll")) { - if (!n.getBoundingClientRect || n === document.body) return ql(); + if (!n.getBoundingClientRect || n === document.body) return Fl(); if (r || t) return n; r = !0; } } while (n = n.parentNode); - return ql(); + return Fl(); } -function nu(e, t) { +function Wl(e, t) { if (e && t) for (var n in t) t.hasOwnProperty(n) && (e[n] = t[n]); return e; } -function ru(e, t) { +function Gl(e, t) { return Math.round(e.top) === Math.round(t.top) && Math.round(e.left) === Math.round(t.left) && Math.round(e.height) === Math.round(t.height) && Math.round(e.width) === Math.round(t.width); } -var iu; -function au(e, t) { +var Kl; +function ql(e, t) { return function() { - if (!iu) { + if (!Kl) { var n = arguments, r = this; - n.length === 1 ? e.call(r, n[0]) : e.apply(r, n), iu = setTimeout(function() { - iu = void 0; + n.length === 1 ? e.call(r, n[0]) : e.apply(r, n), Kl = setTimeout(function() { + Kl = void 0; }, t); } }; } -function ou() { - clearTimeout(iu), iu = void 0; +function Jl() { + clearTimeout(Kl), Kl = void 0; } -function su(e, t, n) { +function Yl(e, t, n) { e.scrollLeft += t, e.scrollTop += n; } -function cu(e) { +function Xl(e) { var t = window.Polymer, n = window.jQuery || window.Zepto; return t && t.dom ? t.dom(e).cloneNode(!0) : n ? n(e).clone(!0)[0] : e.cloneNode(!0); } -function lu(e, t, n) { +function Zl(e, t, n) { var r = {}; return Array.from(e.children).forEach(function(i) { - if (Hl(i, t.draggable, e, !1) && !i.animated && i !== n) { - var a = Jl(i); + if (Al(i, t.draggable, e, !1) && !i.animated && i !== n) { + var a = Il(i); r.left = Math.min(r.left ?? Infinity, a.left), r.top = Math.min(r.top ?? Infinity, a.top), r.right = Math.max(r.right ?? -Infinity, a.right), r.bottom = Math.max(r.bottom ?? -Infinity, a.bottom); } }), r.width = r.right - r.left, r.height = r.bottom - r.top, r.x = r.left, r.y = r.top, r; } -var uu = "Sortable" + (/* @__PURE__ */ new Date()).getTime(); -function du() { +var Ql = "Sortable" + (/* @__PURE__ */ new Date()).getTime(); +function $l() { var e = [], t; return { captureAnimationState: function() { e = [], this.options.animation && [].slice.call(this.el.children).forEach(function(t) { - if (J(t, "display") !== "none" && t !== $.ghost) { + if (Y(t, "display") !== "none" && t !== $.ghost) { e.push({ target: t, - rect: Jl(t) + rect: Il(t) }); - var n = Tl({}, e[e.length - 1].rect); + var n = pl({}, e[e.length - 1].rect); if (t.thisAnimationDuration) { - var r = Gl(t, !0); + var r = Nl(t, !0); r && (n.top -= r.f, n.left -= r.e); } t.fromRect = n; @@ -6058,7 +6145,7 @@ function du() { e.push(t); }, removeAnimationState: function(t) { - e.splice(eu(e, { target: t }), 1); + e.splice(Hl(e, { target: t }), 1); }, animateAll: function(n) { var r = this; @@ -6068,8 +6155,8 @@ function du() { } var i = !1, a = 0; e.forEach(function(e) { - var t = 0, n = e.target, o = n.fromRect, s = Jl(n), c = n.prevFromRect, l = n.prevToRect, u = e.rect, d = Gl(n, !0); - d && (s.top -= d.f, s.left -= d.e), n.toRect = s, n.thisAnimationDuration && ru(c, s) && !ru(o, s) && (u.top - s.top) / (u.left - s.left) === (o.top - s.top) / (o.left - s.left) && (t = pu(u, c, l, r.options)), ru(s, o) || (n.prevFromRect = o, n.prevToRect = s, t ||= r.options.animation, r.animate(n, u, s, t)), t && (i = !0, a = Math.max(a, t), clearTimeout(n.animationResetTimer), n.animationResetTimer = setTimeout(function() { + var t = 0, n = e.target, o = n.fromRect, s = Il(n), c = n.prevFromRect, l = n.prevToRect, u = e.rect, d = Nl(n, !0); + d && (s.top -= d.f, s.left -= d.e), n.toRect = s, n.thisAnimationDuration && Gl(c, s) && !Gl(o, s) && (u.top - s.top) / (u.left - s.left) === (o.top - s.top) / (o.left - s.left) && (t = tu(u, c, l, r.options)), Gl(s, o) || (n.prevFromRect = o, n.prevToRect = s, t ||= r.options.animation, r.animate(n, u, s, t)), t && (i = !0, a = Math.max(a, t), clearTimeout(n.animationResetTimer), n.animationResetTimer = setTimeout(function() { n.animationTime = 0, n.prevFromRect = null, n.fromRect = null, n.prevToRect = null, n.thisAnimationDuration = null; }, t), n.thisAnimationDuration = t); }), clearTimeout(t), i ? t = setTimeout(function() { @@ -6078,27 +6165,27 @@ function du() { }, animate: function(e, t, n, r) { if (r) { - J(e, "transition", ""), J(e, "transform", ""); - var i = Gl(this.el), a = i && i.a, o = i && i.d, s = (t.left - n.left) / (a || 1), c = (t.top - n.top) / (o || 1); - e.animatingX = !!s, e.animatingY = !!c, J(e, "transform", "translate3d(" + s + "px," + c + "px,0)"), this.forRepaintDummy = fu(e), J(e, "transition", "transform " + r + "ms" + (this.options.easing ? " " + this.options.easing : "")), J(e, "transform", "translate3d(0,0,0)"), typeof e.animated == "number" && clearTimeout(e.animated), e.animated = setTimeout(function() { - J(e, "transition", ""), J(e, "transform", ""), e.animated = !1, e.animatingX = !1, e.animatingY = !1; + Y(e, "transition", ""), Y(e, "transform", ""); + var i = Nl(this.el), a = i && i.a, o = i && i.d, s = (t.left - n.left) / (a || 1), c = (t.top - n.top) / (o || 1); + e.animatingX = !!s, e.animatingY = !!c, Y(e, "transform", "translate3d(" + s + "px," + c + "px,0)"), this.forRepaintDummy = eu(e), Y(e, "transition", "transform " + r + "ms" + (this.options.easing ? " " + this.options.easing : "")), Y(e, "transform", "translate3d(0,0,0)"), typeof e.animated == "number" && clearTimeout(e.animated), e.animated = setTimeout(function() { + Y(e, "transition", ""), Y(e, "transform", ""), e.animated = !1, e.animatingX = !1, e.animatingY = !1; }, r); } } }; } -function fu(e) { +function eu(e) { return e.offsetWidth; } -function pu(e, t, n, r) { +function tu(e, t, n, r) { return Math.sqrt((t.top - e.top) ** 2 + (t.left - e.left) ** 2) / Math.sqrt((t.top - n.top) ** 2 + (t.left - n.left) ** 2) * r.animation; } -var mu = [], hu = { initializeByDefault: !0 }, gu = { +var nu = [], ru = { initializeByDefault: !0 }, iu = { mount: function(e) { - for (var t in hu) hu.hasOwnProperty(t) && !(t in e) && (e[t] = hu[t]); - mu.forEach(function(t) { + for (var t in ru) ru.hasOwnProperty(t) && !(t in e) && (e[t] = ru[t]); + nu.forEach(function(t) { if (t.pluginName === e.pluginName) throw `Sortable: Cannot mount plugin ${e.pluginName} more than once`; - }), mu.push(e); + }), nu.push(e); }, pluginEvent: function(e, t, n) { var r = this; @@ -6106,16 +6193,16 @@ var mu = [], hu = { initializeByDefault: !0 }, gu = { r.eventCanceled = !0; }; var i = e + "Global"; - mu.forEach(function(r) { - t[r.pluginName] && (t[r.pluginName][i] && t[r.pluginName][i](Tl({ sortable: t }, n)), t.options[r.pluginName] && t[r.pluginName][e] && t[r.pluginName][e](Tl({ sortable: t }, n))); + nu.forEach(function(r) { + t[r.pluginName] && (t[r.pluginName][i] && t[r.pluginName][i](pl({ sortable: t }, n)), t.options[r.pluginName] && t[r.pluginName][e] && t[r.pluginName][e](pl({ sortable: t }, n))); }); }, initializePlugins: function(e, t, n, r) { - for (var i in mu.forEach(function(r) { + for (var i in nu.forEach(function(r) { var i = r.pluginName; if (e.options[i] || r.initializeByDefault) { var a = new r(e, t, e.options); - a.sortable = e, a.options = e.options, e[i] = a, Cl(n, a.defaults); + a.sortable = e, a.options = e.options, e[i] = a, dl(n, a.defaults); } }), e.options) if (e.options.hasOwnProperty(i)) { var a = this.modifyOption(e, i, e.options[i]); @@ -6124,59 +6211,59 @@ var mu = [], hu = { initializeByDefault: !0 }, gu = { }, getEventProperties: function(e, t) { var n = {}; - return mu.forEach(function(r) { - typeof r.eventProperties == "function" && Cl(n, r.eventProperties.call(t[r.pluginName], e)); + return nu.forEach(function(r) { + typeof r.eventProperties == "function" && dl(n, r.eventProperties.call(t[r.pluginName], e)); }), n; }, modifyOption: function(e, t, n) { var r; - return mu.forEach(function(i) { + return nu.forEach(function(i) { e[i.pluginName] && i.optionListeners && typeof i.optionListeners[t] == "function" && (r = i.optionListeners[t].call(e[i.pluginName], n)); }), r; } }; -function _u(e) { +function au(e) { var t = e.sortable, n = e.rootEl, r = e.name, i = e.targetEl, a = e.cloneEl, o = e.toEl, s = e.fromEl, c = e.oldIndex, l = e.newIndex, u = e.oldDraggableIndex, d = e.newDraggableIndex, f = e.originalEvent, p = e.putSortable, m = e.extraEventProperties; - if (t ||= n && n[uu], t) { + if (t ||= n && n[Ql], t) { var h, g = t.options, _ = "on" + r.charAt(0).toUpperCase() + r.substr(1); - window.CustomEvent && !Nl && !Pl ? h = new CustomEvent(r, { + window.CustomEvent && !xl && !Sl ? h = new CustomEvent(r, { bubbles: !0, cancelable: !0 }) : (h = document.createEvent("Event"), h.initEvent(r, !0, !0)), h.to = o || n, h.from = s || n, h.item = i || n, h.clone = a, h.oldIndex = c, h.newIndex = l, h.oldDraggableIndex = u, h.newDraggableIndex = d, h.originalEvent = f, h.pullMode = p ? p.lastPutMode : void 0; - var v = Tl(Tl({}, m), gu.getEventProperties(r, t)); + var v = pl(pl({}, m), iu.getEventProperties(r, t)); for (var y in v) h[y] = v[y]; n && n.dispatchEvent(h), g[_] && g[_].call(t, h); } } -var vu = ["evt"], yu = function(e, t) { - var n = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {}, r = n.evt, i = El(n, vu); - gu.pluginEvent.bind($)(e, t, Tl({ - dragEl: Y, - parentEl: xu, - ghostEl: X, - rootEl: Z, - nextEl: Su, - lastDownEl: Cu, - cloneEl: Q, - cloneHidden: wu, - dragStarted: Bu, - putSortable: Au, +var ou = ["evt"], su = function(e, t) { + var n = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {}, r = n.evt, i = ml(n, ou); + iu.pluginEvent.bind($)(e, t, pl({ + dragEl: X, + parentEl: lu, + ghostEl: Z, + rootEl: Q, + nextEl: uu, + lastDownEl: du, + cloneEl: fu, + cloneHidden: pu, + dragStarted: ku, + putSortable: yu, activeSortable: $.active, originalEvent: r, - oldIndex: Tu, - oldDraggableIndex: Du, - newIndex: Eu, - newDraggableIndex: Ou, - hideGhostForTarget: ad, - unhideGhostForTarget: od, + oldIndex: mu, + oldDraggableIndex: gu, + newIndex: hu, + newDraggableIndex: _u, + hideGhostForTarget: Ju, + unhideGhostForTarget: Yu, cloneNowHidden: function() { - wu = !0; + pu = !0; }, cloneNowShown: function() { - wu = !1; + pu = !1; }, dispatchSortableEvent: function(e) { - bu({ + cu({ sortable: t, name: e, originalEvent: r @@ -6184,46 +6271,46 @@ var vu = ["evt"], yu = function(e, t) { } }, i)); }; -function bu(e) { - _u(Tl({ - putSortable: Au, - cloneEl: Q, - targetEl: Y, - rootEl: Z, - oldIndex: Tu, - oldDraggableIndex: Du, - newIndex: Eu, - newDraggableIndex: Ou +function cu(e) { + au(pl({ + putSortable: yu, + cloneEl: fu, + targetEl: X, + rootEl: Q, + oldIndex: mu, + oldDraggableIndex: gu, + newIndex: hu, + newDraggableIndex: _u }, e)); } -var Y, xu, X, Z, Su, Cu, Q, wu, Tu, Eu, Du, Ou, ku, Au, ju = !1, Mu = !1, Nu = [], Pu, Fu, Iu, Lu, Ru, zu, Bu, Vu, Hu, Uu = !1, Wu = !1, Gu, Ku, qu = [], Ju = !1, Yu = [], Xu = typeof document < "u", Zu = Ll, Qu = Pl || Nl ? "cssFloat" : "float", $u = Xu && !Rl && !Ll && "draggable" in document.createElement("div"), ed = function() { - if (Xu) { - if (Nl) return !1; +var X, lu, Z, Q, uu, du, fu, pu, mu, hu, gu, _u, vu, yu, bu = !1, xu = !1, Su = [], Cu, wu, Tu, Eu, Du, Ou, ku, Au, ju, Mu = !1, Nu = !1, Pu, Fu, Iu = [], Lu = !1, Ru = [], zu = typeof document < "u", Bu = Tl, Vu = Sl || xl ? "cssFloat" : "float", Hu = zu && !El && !Tl && "draggable" in document.createElement("div"), Uu = function() { + if (zu) { + if (xl) return !1; var e = document.createElement("x"); return e.style.cssText = "pointer-events:auto", e.style.pointerEvents === "auto"; } -}(), td = function(e, t) { - var n = J(e), r = parseInt(n.width) - parseInt(n.paddingLeft) - parseInt(n.paddingRight) - parseInt(n.borderLeftWidth) - parseInt(n.borderRightWidth), i = Xl(e, 0, t), a = Xl(e, 1, t), o = i && J(i), s = a && J(a), c = o && parseInt(o.marginLeft) + parseInt(o.marginRight) + Jl(i).width, l = s && parseInt(s.marginLeft) + parseInt(s.marginRight) + Jl(a).width; +}(), Wu = function(e, t) { + var n = Y(e), r = parseInt(n.width) - parseInt(n.paddingLeft) - parseInt(n.paddingRight) - parseInt(n.borderLeftWidth) - parseInt(n.borderRightWidth), i = Rl(e, 0, t), a = Rl(e, 1, t), o = i && Y(i), s = a && Y(a), c = o && parseInt(o.marginLeft) + parseInt(o.marginRight) + Il(i).width, l = s && parseInt(s.marginLeft) + parseInt(s.marginRight) + Il(a).width; if (n.display === "flex") return n.flexDirection === "column" || n.flexDirection === "column-reverse" ? "vertical" : "horizontal"; if (n.display === "grid") return n.gridTemplateColumns.split(" ").length <= 1 ? "vertical" : "horizontal"; if (i && o.float && o.float !== "none") { var u = o.float === "left" ? "left" : "right"; return a && (s.clear === "both" || s.clear === u) ? "vertical" : "horizontal"; } - return i && (o.display === "block" || o.display === "flex" || o.display === "table" || o.display === "grid" || c >= r && n[Qu] === "none" || a && n[Qu] === "none" && c + l > r) ? "vertical" : "horizontal"; -}, nd = function(e, t, n) { + return i && (o.display === "block" || o.display === "flex" || o.display === "table" || o.display === "grid" || c >= r && n[Vu] === "none" || a && n[Vu] === "none" && c + l > r) ? "vertical" : "horizontal"; +}, Gu = function(e, t, n) { var r = n ? e.left : e.top, i = n ? e.right : e.bottom, a = n ? e.width : e.height, o = n ? t.left : t.top, s = n ? t.right : t.bottom, c = n ? t.width : t.height; return r === o || i === s || r + a / 2 === o + c / 2; -}, rd = function(e, t) { +}, Ku = function(e, t) { var n; - return Nu.some(function(r) { - var i = r[uu].options.emptyInsertThreshold; - if (i && !Zl(r)) { - var a = Jl(r), o = e >= a.left - i && e <= a.right + i, s = t >= a.top - i && t <= a.bottom + i; + return Su.some(function(r) { + var i = r[Ql].options.emptyInsertThreshold; + if (i && !zl(r)) { + var a = Il(r), o = e >= a.left - i && e <= a.right + i, s = t >= a.top - i && t <= a.bottom + i; if (o && s) return n = r; } }), n; -}, id = function(e) { +}, qu = function(e) { function t(e, n) { return function(r, i, a, o) { var s = r.options.group.name && i.options.group.name && r.options.group.name === i.options.group.name; @@ -6236,31 +6323,31 @@ var Y, xu, X, Z, Su, Cu, Q, wu, Tu, Eu, Du, Ou, ku, Au, ju = !1, Mu = !1, Nu = [ }; } var n = {}, r = e.group; - (!r || Al(r) != "object") && (r = { name: r }), n.name = r.name, n.checkPull = t(r.pull, !0), n.checkPut = t(r.put), n.revertClone = r.revertClone, e.group = n; -}, ad = function() { - !ed && X && J(X, "display", "none"); -}, od = function() { - !ed && X && J(X, "display", ""); + (!r || vl(r) != "object") && (r = { name: r }), n.name = r.name, n.checkPull = t(r.pull, !0), n.checkPut = t(r.put), n.revertClone = r.revertClone, e.group = n; +}, Ju = function() { + !Uu && Z && Y(Z, "display", "none"); +}, Yu = function() { + !Uu && Z && Y(Z, "display", ""); }; -Xu && !Rl && document.addEventListener("click", function(e) { - if (Mu) return e.preventDefault(), e.stopPropagation && e.stopPropagation(), e.stopImmediatePropagation && e.stopImmediatePropagation(), Mu = !1, !1; +zu && !El && document.addEventListener("click", function(e) { + if (xu) return e.preventDefault(), e.stopPropagation && e.stopPropagation(), e.stopImmediatePropagation && e.stopImmediatePropagation(), xu = !1, !1; }, !0); -var sd = function(e) { - if (Y) { +var Xu = function(e) { + if (X) { e = e.touches ? e.touches[0] : e; - var t = rd(e.clientX, e.clientY); + var t = Ku(e.clientX, e.clientY); if (t) { var n = {}; for (var r in e) e.hasOwnProperty(r) && (n[r] = e[r]); - n.target = n.rootEl = t, n.preventDefault = void 0, n.stopPropagation = void 0, t[uu]._onDragOver(n); + n.target = n.rootEl = t, n.preventDefault = void 0, n.stopPropagation = void 0, t[Ql]._onDragOver(n); } } -}, cd = function(e) { - Y && Y.parentNode[uu]._isOutsideThisEl(e.target); +}, Zu = function(e) { + X && X.parentNode[Ql]._isOutsideThisEl(e.target); }; function $(e, t) { if (!(e && e.nodeType && e.nodeType === 1)) throw `Sortable: \`el\` must be an HTMLElement, not ${{}.toString.call(e)}`; - this.el = e, this.options = t = Cl({}, t), e[uu] = this; + this.el = e, this.options = t = dl({}, t), e[Ql] = this; var n = { group: null, sort: !0, @@ -6273,7 +6360,7 @@ function $(e, t) { invertedSwapThreshold: null, removeCloneOnHide: !0, direction: function() { - return td(e, this.options); + return Wu(e, this.options); }, ghostClass: "sortable-ghost", chosenClass: "sortable-chosen", @@ -6300,80 +6387,80 @@ function $(e, t) { x: 0, y: 0 }, - supportPointer: $.supportPointer !== !1 && "PointerEvent" in window && (!Il || Ll), + supportPointer: $.supportPointer !== !1 && "PointerEvent" in window && (!wl || Tl), emptyInsertThreshold: 5 }; - for (var r in gu.initializePlugins(this, e, n), n) !(r in t) && (t[r] = n[r]); - for (var i in id(t), this) i.charAt(0) === "_" && typeof this[i] == "function" && (this[i] = this[i].bind(this)); - this.nativeDraggable = !t.forceFallback && $u, this.nativeDraggable && (this.options.touchStartThreshold = 1), t.supportPointer ? K(e, "pointerdown", this._onTapStart) : (K(e, "mousedown", this._onTapStart), K(e, "touchstart", this._onTapStart)), this.nativeDraggable && (K(e, "dragover", this), K(e, "dragenter", this)), Nu.push(this.el), t.store && t.store.get && this.sort(t.store.get(this) || []), Cl(this, du()); + for (var r in iu.initializePlugins(this, e, n), n) !(r in t) && (t[r] = n[r]); + for (var i in qu(t), this) i.charAt(0) === "_" && typeof this[i] == "function" && (this[i] = this[i].bind(this)); + this.nativeDraggable = !t.forceFallback && Hu, this.nativeDraggable && (this.options.touchStartThreshold = 1), t.supportPointer ? q(e, "pointerdown", this._onTapStart) : (q(e, "mousedown", this._onTapStart), q(e, "touchstart", this._onTapStart)), this.nativeDraggable && (q(e, "dragover", this), q(e, "dragenter", this)), Su.push(this.el), t.store && t.store.get && this.sort(t.store.get(this) || []), dl(this, $l()); } $.prototype = { constructor: $, _isOutsideThisEl: function(e) { - !this.el.contains(e) && e !== this.el && (Vu = null); + !this.el.contains(e) && e !== this.el && (Au = null); }, _getDirection: function(e, t) { - return typeof this.options.direction == "function" ? this.options.direction.call(this, e, t, Y) : this.options.direction; + return typeof this.options.direction == "function" ? this.options.direction.call(this, e, t, X) : this.options.direction; }, _onTapStart: function(e) { if (e.cancelable) { var t = this, n = this.el, r = this.options, i = r.preventOnFilter, a = e.type, o = e.touches && e.touches[0] || e.pointerType && e.pointerType === "touch" && e, s = (o || e).target, c = e.target.shadowRoot && (e.path && e.path[0] || e.composedPath && e.composedPath()[0]) || s, l = r.filter; - if (vd(n), !Y && !(/mousedown|pointerdown/.test(a) && e.button !== 0 || r.disabled) && !c.isContentEditable && !(!this.nativeDraggable && Il && s && s.tagName.toUpperCase() === "SELECT") && (s = Hl(s, r.draggable, n, !1), !(s && s.animated) && Cu !== s)) { - if (Tu = Ql(s), Du = Ql(s, r.draggable), typeof l == "function") { + if (sd(n), !X && !(/mousedown|pointerdown/.test(a) && e.button !== 0 || r.disabled) && !c.isContentEditable && !(!this.nativeDraggable && wl && s && s.tagName.toUpperCase() === "SELECT") && (s = Al(s, r.draggable, n, !1), !(s && s.animated) && du !== s)) { + if (mu = Bl(s), gu = Bl(s, r.draggable), typeof l == "function") { if (l.call(this, e, s, this)) { - bu({ + cu({ sortable: t, rootEl: c, name: "filter", targetEl: s, toEl: n, fromEl: n - }), yu("filter", t, { evt: e }), i && e.preventDefault(); + }), su("filter", t, { evt: e }), i && e.preventDefault(); return; } } else if (l && (l = l.split(",").some(function(r) { - if (r = Hl(c, r.trim(), n, !1), r) return bu({ + if (r = Al(c, r.trim(), n, !1), r) return cu({ sortable: t, rootEl: r, name: "filter", targetEl: s, fromEl: n, toEl: n - }), yu("filter", t, { evt: e }), !0; + }), su("filter", t, { evt: e }), !0; }), l)) { i && e.preventDefault(); return; } - (!r.handle || Hl(c, r.handle, n, !1)) && this._prepareDragStart(e, o, s); + (!r.handle || Al(c, r.handle, n, !1)) && this._prepareDragStart(e, o, s); } } }, _prepareDragStart: function(e, t, n) { var r = this, i = r.el, a = r.options, o = i.ownerDocument, s; - if (n && !Y && n.parentNode === i) { - var c = Jl(n); - if (Z = i, Y = n, xu = Y.parentNode, Su = Y.nextSibling, Cu = n, ku = a.group, $.dragged = Y, Pu = { - target: Y, + if (n && !X && n.parentNode === i) { + var c = Il(n); + if (Q = i, X = n, lu = X.parentNode, uu = X.nextSibling, du = n, vu = a.group, $.dragged = X, Cu = { + target: X, clientX: (t || e).clientX, clientY: (t || e).clientY - }, Ru = Pu.clientX - c.left, zu = Pu.clientY - c.top, this._lastX = (t || e).clientX, this._lastY = (t || e).clientY, Y.style["will-change"] = "all", s = function() { - if (yu("delayEnded", r, { evt: e }), $.eventCanceled) { + }, Du = Cu.clientX - c.left, Ou = Cu.clientY - c.top, this._lastX = (t || e).clientX, this._lastY = (t || e).clientY, X.style["will-change"] = "all", s = function() { + if (su("delayEnded", r, { evt: e }), $.eventCanceled) { r._onDrop(); return; } - r._disableDelayedDragEvents(), !Fl && r.nativeDraggable && (Y.draggable = !0), r._triggerDragStart(e, t), bu({ + r._disableDelayedDragEvents(), !Cl && r.nativeDraggable && (X.draggable = !0), r._triggerDragStart(e, t), cu({ sortable: r, name: "choose", originalEvent: e - }), Wl(Y, a.chosenClass, !0); + }), Ml(X, a.chosenClass, !0); }, a.ignore.split(",").forEach(function(e) { - Kl(Y, e.trim(), dd); - }), K(o, "dragover", sd), K(o, "mousemove", sd), K(o, "touchmove", sd), a.supportPointer ? (K(o, "pointerup", r._onDrop), !this.nativeDraggable && K(o, "pointercancel", r._onDrop)) : (K(o, "mouseup", r._onDrop), K(o, "touchend", r._onDrop), K(o, "touchcancel", r._onDrop)), Fl && this.nativeDraggable && (this.options.touchStartThreshold = 4, Y.draggable = !0), yu("delayStart", this, { evt: e }), a.delay && (!a.delayOnTouchOnly || t) && (!this.nativeDraggable || !(Pl || Nl))) { + Pl(X, e.trim(), ed); + }), q(o, "dragover", Xu), q(o, "mousemove", Xu), q(o, "touchmove", Xu), a.supportPointer ? (q(o, "pointerup", r._onDrop), !this.nativeDraggable && q(o, "pointercancel", r._onDrop)) : (q(o, "mouseup", r._onDrop), q(o, "touchend", r._onDrop), q(o, "touchcancel", r._onDrop)), Cl && this.nativeDraggable && (this.options.touchStartThreshold = 4, X.draggable = !0), su("delayStart", this, { evt: e }), a.delay && (!a.delayOnTouchOnly || t) && (!this.nativeDraggable || !(Sl || xl))) { if ($.eventCanceled) { this._onDrop(); return; } - a.supportPointer ? (K(o, "pointerup", r._disableDelayedDrag), K(o, "pointercancel", r._disableDelayedDrag)) : (K(o, "mouseup", r._disableDelayedDrag), K(o, "touchend", r._disableDelayedDrag), K(o, "touchcancel", r._disableDelayedDrag)), K(o, "mousemove", r._delayedDragTouchMoveHandler), K(o, "touchmove", r._delayedDragTouchMoveHandler), a.supportPointer && K(o, "pointermove", r._delayedDragTouchMoveHandler), r._dragStartTimer = setTimeout(s, a.delay); + a.supportPointer ? (q(o, "pointerup", r._disableDelayedDrag), q(o, "pointercancel", r._disableDelayedDrag)) : (q(o, "mouseup", r._disableDelayedDrag), q(o, "touchend", r._disableDelayedDrag), q(o, "touchcancel", r._disableDelayedDrag)), q(o, "mousemove", r._delayedDragTouchMoveHandler), q(o, "touchmove", r._delayedDragTouchMoveHandler), a.supportPointer && q(o, "pointermove", r._delayedDragTouchMoveHandler), r._dragStartTimer = setTimeout(s, a.delay); } else s(); } }, @@ -6382,25 +6469,25 @@ $.prototype = { Math.max(Math.abs(t.clientX - this._lastX), Math.abs(t.clientY - this._lastY)) >= Math.floor(this.options.touchStartThreshold / (this.nativeDraggable && window.devicePixelRatio || 1)) && this._disableDelayedDrag(); }, _disableDelayedDrag: function() { - Y && dd(Y), clearTimeout(this._dragStartTimer), this._disableDelayedDragEvents(); + X && ed(X), clearTimeout(this._dragStartTimer), this._disableDelayedDragEvents(); }, _disableDelayedDragEvents: function() { var e = this.el.ownerDocument; - q(e, "mouseup", this._disableDelayedDrag), q(e, "touchend", this._disableDelayedDrag), q(e, "touchcancel", this._disableDelayedDrag), q(e, "pointerup", this._disableDelayedDrag), q(e, "pointercancel", this._disableDelayedDrag), q(e, "mousemove", this._delayedDragTouchMoveHandler), q(e, "touchmove", this._delayedDragTouchMoveHandler), q(e, "pointermove", this._delayedDragTouchMoveHandler); + J(e, "mouseup", this._disableDelayedDrag), J(e, "touchend", this._disableDelayedDrag), J(e, "touchcancel", this._disableDelayedDrag), J(e, "pointerup", this._disableDelayedDrag), J(e, "pointercancel", this._disableDelayedDrag), J(e, "mousemove", this._delayedDragTouchMoveHandler), J(e, "touchmove", this._delayedDragTouchMoveHandler), J(e, "pointermove", this._delayedDragTouchMoveHandler); }, _triggerDragStart: function(e, t) { - t ||= e.pointerType == "touch" && e, !this.nativeDraggable || t ? this.options.supportPointer ? K(document, "pointermove", this._onTouchMove) : t ? K(document, "touchmove", this._onTouchMove) : K(document, "mousemove", this._onTouchMove) : (K(Y, "dragend", this), K(Z, "dragstart", this._onDragStart)); + t ||= e.pointerType == "touch" && e, !this.nativeDraggable || t ? this.options.supportPointer ? q(document, "pointermove", this._onTouchMove) : t ? q(document, "touchmove", this._onTouchMove) : q(document, "mousemove", this._onTouchMove) : (q(X, "dragend", this), q(Q, "dragstart", this._onDragStart)); try { - document.selection ? yd(function() { + document.selection ? cd(function() { document.selection.empty(); }) : window.getSelection().removeAllRanges(); } catch {} }, _dragStarted: function(e, t) { - if (ju = !1, Z && Y) { - yu("dragStarted", this, { evt: t }), this.nativeDraggable && K(document, "dragover", cd); + if (bu = !1, Q && X) { + su("dragStarted", this, { evt: t }), this.nativeDraggable && q(document, "dragover", Zu); var n = this.options; - !e && Wl(Y, n.dragClass, !1), Wl(Y, n.ghostClass, !0), $.active = this, e && this._appendGhost(), bu({ + !e && Ml(X, n.dragClass, !1), Ml(X, n.ghostClass, !0), $.active = this, e && this._appendGhost(), cu({ sortable: this, name: "start", originalEvent: t @@ -6408,33 +6495,33 @@ $.prototype = { } else this._nulling(); }, _emulateDragOver: function() { - if (Fu) { - this._lastX = Fu.clientX, this._lastY = Fu.clientY, ad(); - for (var e = document.elementFromPoint(Fu.clientX, Fu.clientY), t = e; e && e.shadowRoot && (e = e.shadowRoot.elementFromPoint(Fu.clientX, Fu.clientY), e !== t);) t = e; - if (Y.parentNode[uu]._isOutsideThisEl(e), t) do { - if (t[uu]) { + if (wu) { + this._lastX = wu.clientX, this._lastY = wu.clientY, Ju(); + for (var e = document.elementFromPoint(wu.clientX, wu.clientY), t = e; e && e.shadowRoot && (e = e.shadowRoot.elementFromPoint(wu.clientX, wu.clientY), e !== t);) t = e; + if (X.parentNode[Ql]._isOutsideThisEl(e), t) do { + if (t[Ql]) { var n = void 0; - if (n = t[uu]._onDragOver({ - clientX: Fu.clientX, - clientY: Fu.clientY, + if (n = t[Ql]._onDragOver({ + clientX: wu.clientX, + clientY: wu.clientY, target: e, rootEl: t }), n && !this.options.dragoverBubble) break; } e = t; - } while (t = Vl(t)); - od(); + } while (t = kl(t)); + Yu(); } }, _onTouchMove: function(e) { - if (Pu) { - var t = this.options, n = t.fallbackTolerance, r = t.fallbackOffset, i = e.touches ? e.touches[0] : e, a = X && Gl(X, !0), o = X && a && a.a, s = X && a && a.d, c = Zu && Ku && $l(Ku), l = (i.clientX - Pu.clientX + r.x) / (o || 1) + (c ? c[0] - qu[0] : 0) / (o || 1), u = (i.clientY - Pu.clientY + r.y) / (s || 1) + (c ? c[1] - qu[1] : 0) / (s || 1); - if (!$.active && !ju) { + if (Cu) { + var t = this.options, n = t.fallbackTolerance, r = t.fallbackOffset, i = e.touches ? e.touches[0] : e, a = Z && Nl(Z, !0), o = Z && a && a.a, s = Z && a && a.d, c = Bu && Fu && Vl(Fu), l = (i.clientX - Cu.clientX + r.x) / (o || 1) + (c ? c[0] - Iu[0] : 0) / (o || 1), u = (i.clientY - Cu.clientY + r.y) / (s || 1) + (c ? c[1] - Iu[1] : 0) / (s || 1); + if (!$.active && !bu) { if (n && Math.max(Math.abs(i.clientX - this._lastX), Math.abs(i.clientY - this._lastY)) < n) return; this._onDragStart(e, !0); } - if (X) { - a ? (a.e += l - (Iu || 0), a.f += u - (Lu || 0)) : a = { + if (Z) { + a ? (a.e += l - (Tu || 0), a.f += u - (Eu || 0)) : a = { a: 1, b: 0, c: 0, @@ -6443,39 +6530,39 @@ $.prototype = { f: u }; var d = `matrix(${a.a},${a.b},${a.c},${a.d},${a.e},${a.f})`; - J(X, "webkitTransform", d), J(X, "mozTransform", d), J(X, "msTransform", d), J(X, "transform", d), Iu = l, Lu = u, Fu = i; + Y(Z, "webkitTransform", d), Y(Z, "mozTransform", d), Y(Z, "msTransform", d), Y(Z, "transform", d), Tu = l, Eu = u, wu = i; } e.cancelable && e.preventDefault(); } }, _appendGhost: function() { - if (!X) { - var e = this.options.fallbackOnBody ? document.body : Z, t = Jl(Y, !0, Zu, !0, e), n = this.options; - if (Zu) { - for (Ku = e; J(Ku, "position") === "static" && J(Ku, "transform") === "none" && Ku !== document;) Ku = Ku.parentNode; - Ku !== document.body && Ku !== document.documentElement ? (Ku === document && (Ku = ql()), t.top += Ku.scrollTop, t.left += Ku.scrollLeft) : Ku = ql(), qu = $l(Ku); + if (!Z) { + var e = this.options.fallbackOnBody ? document.body : Q, t = Il(X, !0, Bu, !0, e), n = this.options; + if (Bu) { + for (Fu = e; Y(Fu, "position") === "static" && Y(Fu, "transform") === "none" && Fu !== document;) Fu = Fu.parentNode; + Fu !== document.body && Fu !== document.documentElement ? (Fu === document && (Fu = Fl()), t.top += Fu.scrollTop, t.left += Fu.scrollLeft) : Fu = Fl(), Iu = Vl(Fu); } - X = Y.cloneNode(!0), Wl(X, n.ghostClass, !1), Wl(X, n.fallbackClass, !0), Wl(X, n.dragClass, !0), J(X, "transition", ""), J(X, "transform", ""), J(X, "box-sizing", "border-box"), J(X, "margin", 0), J(X, "top", t.top), J(X, "left", t.left), J(X, "width", t.width), J(X, "height", t.height), J(X, "opacity", "0.8"), J(X, "position", Zu ? "absolute" : "fixed"), J(X, "zIndex", "100000"), J(X, "pointerEvents", "none"), $.ghost = X, e.appendChild(X), J(X, "transform-origin", Ru / parseInt(X.style.width) * 100 + "% " + zu / parseInt(X.style.height) * 100 + "%"); + Z = X.cloneNode(!0), Ml(Z, n.ghostClass, !1), Ml(Z, n.fallbackClass, !0), Ml(Z, n.dragClass, !0), Y(Z, "transition", ""), Y(Z, "transform", ""), Y(Z, "box-sizing", "border-box"), Y(Z, "margin", 0), Y(Z, "top", t.top), Y(Z, "left", t.left), Y(Z, "width", t.width), Y(Z, "height", t.height), Y(Z, "opacity", "0.8"), Y(Z, "position", Bu ? "absolute" : "fixed"), Y(Z, "zIndex", "100000"), Y(Z, "pointerEvents", "none"), $.ghost = Z, e.appendChild(Z), Y(Z, "transform-origin", Du / parseInt(Z.style.width) * 100 + "% " + Ou / parseInt(Z.style.height) * 100 + "%"); } }, _onDragStart: function(e, t) { var n = this, r = e.dataTransfer, i = n.options; - if (yu("dragStart", this, { evt: e }), $.eventCanceled) { + if (su("dragStart", this, { evt: e }), $.eventCanceled) { this._onDrop(); return; } - yu("setupClone", this), $.eventCanceled || (Q = cu(Y), Q.removeAttribute("id"), Q.draggable = !1, Q.style["will-change"] = "", this._hideClone(), Wl(Q, this.options.chosenClass, !1), $.clone = Q), n.cloneId = yd(function() { - yu("clone", n), !$.eventCanceled && (n.options.removeCloneOnHide || Z.insertBefore(Q, Y), n._hideClone(), bu({ + su("setupClone", this), $.eventCanceled || (fu = Xl(X), fu.removeAttribute("id"), fu.draggable = !1, fu.style["will-change"] = "", this._hideClone(), Ml(fu, this.options.chosenClass, !1), $.clone = fu), n.cloneId = cd(function() { + su("clone", n), !$.eventCanceled && (n.options.removeCloneOnHide || Q.insertBefore(fu, X), n._hideClone(), cu({ sortable: n, name: "clone" })); - }), !t && Wl(Y, i.dragClass, !0), t ? (Mu = !0, n._loopId = setInterval(n._emulateDragOver, 50)) : (q(document, "mouseup", n._onDrop), q(document, "touchend", n._onDrop), q(document, "touchcancel", n._onDrop), r && (r.effectAllowed = "move", i.setData && i.setData.call(n, r, Y)), K(document, "drop", n), J(Y, "transform", "translateZ(0)")), ju = !0, n._dragStartId = yd(n._dragStarted.bind(n, t, e)), K(document, "selectstart", n), Bu = !0, window.getSelection().removeAllRanges(), Il && J(document.body, "user-select", "none"); + }), !t && Ml(X, i.dragClass, !0), t ? (xu = !0, n._loopId = setInterval(n._emulateDragOver, 50)) : (J(document, "mouseup", n._onDrop), J(document, "touchend", n._onDrop), J(document, "touchcancel", n._onDrop), r && (r.effectAllowed = "move", i.setData && i.setData.call(n, r, X)), q(document, "drop", n), Y(X, "transform", "translateZ(0)")), bu = !0, n._dragStartId = cd(n._dragStarted.bind(n, t, e)), q(document, "selectstart", n), ku = !0, window.getSelection().removeAllRanges(), wl && Y(document.body, "user-select", "none"); }, _onDragOver: function(e) { - var t = this.el, n = e.target, r, i, a, o = this.options, s = o.group, c = $.active, l = ku === s, u = o.sort, d = Au || c, f, p = this, m = !1; - if (Ju) return; + var t = this.el, n = e.target, r, i, a, o = this.options, s = o.group, c = $.active, l = vu === s, u = o.sort, d = yu || c, f, p = this, m = !1; + if (Lu) return; function h(o, s) { - yu(o, p, Tl({ + su(o, p, pl({ evt: e, isOwner: l, axis: f ? "vertical" : "horizontal", @@ -6487,7 +6574,7 @@ $.prototype = { target: n, completed: _, onMove: function(n, i) { - return ud(Z, t, Y, r, n, Jl(n), e, i); + return $u(Q, t, X, r, n, Il(n), e, i); }, changed: v }, s)); @@ -6496,121 +6583,121 @@ $.prototype = { h("dragOverAnimationCapture"), p.captureAnimationState(), p !== d && d.captureAnimationState(); } function _(r) { - return h("dragOverCompleted", { insertion: r }), r && (l ? c._hideClone() : c._showClone(p), p !== d && (Wl(Y, Au ? Au.options.ghostClass : c.options.ghostClass, !1), Wl(Y, o.ghostClass, !0)), Au !== p && p !== $.active ? Au = p : p === $.active && Au && (Au = null), d === p && (p._ignoreWhileAnimating = n), p.animateAll(function() { + return h("dragOverCompleted", { insertion: r }), r && (l ? c._hideClone() : c._showClone(p), p !== d && (Ml(X, yu ? yu.options.ghostClass : c.options.ghostClass, !1), Ml(X, o.ghostClass, !0)), yu !== p && p !== $.active ? yu = p : p === $.active && yu && (yu = null), d === p && (p._ignoreWhileAnimating = n), p.animateAll(function() { h("dragOverAnimationComplete"), p._ignoreWhileAnimating = null; - }), p !== d && (d.animateAll(), d._ignoreWhileAnimating = null)), (n === Y && !Y.animated || n === t && !n.animated) && (Vu = null), !o.dragoverBubble && !e.rootEl && n !== document && (Y.parentNode[uu]._isOutsideThisEl(e.target), !r && sd(e)), !o.dragoverBubble && e.stopPropagation && e.stopPropagation(), m = !0; + }), p !== d && (d.animateAll(), d._ignoreWhileAnimating = null)), (n === X && !X.animated || n === t && !n.animated) && (Au = null), !o.dragoverBubble && !e.rootEl && n !== document && (X.parentNode[Ql]._isOutsideThisEl(e.target), !r && Xu(e)), !o.dragoverBubble && e.stopPropagation && e.stopPropagation(), m = !0; } function v() { - Eu = Ql(Y), Ou = Ql(Y, o.draggable), bu({ + hu = Bl(X), _u = Bl(X, o.draggable), cu({ sortable: p, name: "change", toEl: t, - newIndex: Eu, - newDraggableIndex: Ou, + newIndex: hu, + newDraggableIndex: _u, originalEvent: e }); } - if (e.preventDefault !== void 0 && e.cancelable && e.preventDefault(), n = Hl(n, o.draggable, t, !0), h("dragOver"), $.eventCanceled) return m; - if (Y.contains(e.target) || n.animated && n.animatingX && n.animatingY || p._ignoreWhileAnimating === n) return _(!1); - if (Mu = !1, c && !o.disabled && (l ? u || (a = xu !== Z) : Au === this || (this.lastPutMode = ku.checkPull(this, c, Y, e)) && s.checkPut(this, c, Y, e))) { - if (f = this._getDirection(e, n) === "vertical", r = Jl(Y), h("dragOverValid"), $.eventCanceled) return m; - if (a) return xu = Z, g(), this._hideClone(), h("revert"), $.eventCanceled || (Su ? Z.insertBefore(Y, Su) : Z.appendChild(Y)), _(!0); - var y = Zl(t, o.draggable); - if (!y || md(e, f, this) && !y.animated) { - if (y === Y) return _(!1); - if (y && t === e.target && (n = y), n && (i = Jl(n)), ud(Z, t, Y, r, n, i, e, !!n) !== !1) return g(), y && y.nextSibling ? t.insertBefore(Y, y.nextSibling) : t.appendChild(Y), xu = t, v(), _(!0); - } else if (y && pd(e, f, this)) { - var b = Xl(t, 0, o, !0); - if (b === Y) return _(!1); - if (n = b, i = Jl(n), ud(Z, t, Y, r, n, i, e, !1) !== !1) return g(), t.insertBefore(Y, b), xu = t, v(), _(!0); + if (e.preventDefault !== void 0 && e.cancelable && e.preventDefault(), n = Al(n, o.draggable, t, !0), h("dragOver"), $.eventCanceled) return m; + if (X.contains(e.target) || n.animated && n.animatingX && n.animatingY || p._ignoreWhileAnimating === n) return _(!1); + if (xu = !1, c && !o.disabled && (l ? u || (a = lu !== Q) : yu === this || (this.lastPutMode = vu.checkPull(this, c, X, e)) && s.checkPut(this, c, X, e))) { + if (f = this._getDirection(e, n) === "vertical", r = Il(X), h("dragOverValid"), $.eventCanceled) return m; + if (a) return lu = Q, g(), this._hideClone(), h("revert"), $.eventCanceled || (uu ? Q.insertBefore(X, uu) : Q.appendChild(X)), _(!0); + var y = zl(t, o.draggable); + if (!y || rd(e, f, this) && !y.animated) { + if (y === X) return _(!1); + if (y && t === e.target && (n = y), n && (i = Il(n)), $u(Q, t, X, r, n, i, e, !!n) !== !1) return g(), y && y.nextSibling ? t.insertBefore(X, y.nextSibling) : t.appendChild(X), lu = t, v(), _(!0); + } else if (y && nd(e, f, this)) { + var b = Rl(t, 0, o, !0); + if (b === X) return _(!1); + if (n = b, i = Il(n), $u(Q, t, X, r, n, i, e, !1) !== !1) return g(), t.insertBefore(X, b), lu = t, v(), _(!0); } else if (n.parentNode === t) { - i = Jl(n); - var x = 0, S, C = Y.parentNode !== t, w = !nd(Y.animated && Y.toRect || r, n.animated && n.toRect || i, f), T = f ? "top" : "left", E = Yl(n, "top", "top") || Yl(Y, "top", "top"), D = E ? E.scrollTop : void 0; - Vu !== n && (S = i[T], Uu = !1, Wu = !w && o.invertSwap || C), x = hd(e, n, i, f, w ? 1 : o.swapThreshold, o.invertedSwapThreshold == null ? o.swapThreshold : o.invertedSwapThreshold, Wu, Vu === n); + i = Il(n); + var x = 0, S, C = X.parentNode !== t, w = !Gu(X.animated && X.toRect || r, n.animated && n.toRect || i, f), T = f ? "top" : "left", E = Ll(n, "top", "top") || Ll(X, "top", "top"), D = E ? E.scrollTop : void 0; + Au !== n && (S = i[T], Mu = !1, Nu = !w && o.invertSwap || C), x = id(e, n, i, f, w ? 1 : o.swapThreshold, o.invertedSwapThreshold == null ? o.swapThreshold : o.invertedSwapThreshold, Nu, Au === n); var O; if (x !== 0) { - var k = Ql(Y); + var k = Bl(X); do - k -= x, O = xu.children[k]; - while (O && (J(O, "display") === "none" || O === X)); + k -= x, O = lu.children[k]; + while (O && (Y(O, "display") === "none" || O === Z)); } if (x === 0 || O === n) return _(!1); - Vu = n, Hu = x; + Au = n, ju = x; var A = n.nextElementSibling, j = !1; j = x === 1; - var M = ud(Z, t, Y, r, n, i, e, j); - if (M !== !1) return (M === 1 || M === -1) && (j = M === 1), Ju = !0, setTimeout(fd, 30), g(), j && !A ? t.appendChild(Y) : n.parentNode.insertBefore(Y, j ? A : n), E && su(E, 0, D - E.scrollTop), xu = Y.parentNode, S !== void 0 && !Wu && (Gu = Math.abs(S - Jl(n)[T])), v(), _(!0); + var M = $u(Q, t, X, r, n, i, e, j); + if (M !== !1) return (M === 1 || M === -1) && (j = M === 1), Lu = !0, setTimeout(td, 30), g(), j && !A ? t.appendChild(X) : n.parentNode.insertBefore(X, j ? A : n), E && Yl(E, 0, D - E.scrollTop), lu = X.parentNode, S !== void 0 && !Nu && (Pu = Math.abs(S - Il(n)[T])), v(), _(!0); } - if (t.contains(Y)) return _(!1); + if (t.contains(X)) return _(!1); } return !1; }, _ignoreWhileAnimating: null, _offMoveEvents: function() { - q(document, "mousemove", this._onTouchMove), q(document, "touchmove", this._onTouchMove), q(document, "pointermove", this._onTouchMove), q(document, "dragover", sd), q(document, "mousemove", sd), q(document, "touchmove", sd); + J(document, "mousemove", this._onTouchMove), J(document, "touchmove", this._onTouchMove), J(document, "pointermove", this._onTouchMove), J(document, "dragover", Xu), J(document, "mousemove", Xu), J(document, "touchmove", Xu); }, _offUpEvents: function() { var e = this.el.ownerDocument; - q(e, "mouseup", this._onDrop), q(e, "touchend", this._onDrop), q(e, "pointerup", this._onDrop), q(e, "pointercancel", this._onDrop), q(e, "touchcancel", this._onDrop), q(document, "selectstart", this); + J(e, "mouseup", this._onDrop), J(e, "touchend", this._onDrop), J(e, "pointerup", this._onDrop), J(e, "pointercancel", this._onDrop), J(e, "touchcancel", this._onDrop), J(document, "selectstart", this); }, _onDrop: function(e) { var t = this.el, n = this.options; - if (Eu = Ql(Y), Ou = Ql(Y, n.draggable), yu("drop", this, { evt: e }), xu = Y && Y.parentNode, Eu = Ql(Y), Ou = Ql(Y, n.draggable), $.eventCanceled) { + if (hu = Bl(X), _u = Bl(X, n.draggable), su("drop", this, { evt: e }), lu = X && X.parentNode, hu = Bl(X), _u = Bl(X, n.draggable), $.eventCanceled) { this._nulling(); return; } - ju = !1, Wu = !1, Uu = !1, clearInterval(this._loopId), clearTimeout(this._dragStartTimer), bd(this.cloneId), bd(this._dragStartId), this.nativeDraggable && (q(document, "drop", this), q(t, "dragstart", this._onDragStart)), this._offMoveEvents(), this._offUpEvents(), Il && J(document.body, "user-select", ""), J(Y, "transform", ""), e && (Bu && (e.cancelable && e.preventDefault(), !n.dropBubble && e.stopPropagation()), X && X.parentNode && X.parentNode.removeChild(X), (Z === xu || Au && Au.lastPutMode !== "clone") && Q && Q.parentNode && Q.parentNode.removeChild(Q), Y && (this.nativeDraggable && q(Y, "dragend", this), dd(Y), Y.style["will-change"] = "", Bu && !ju && Wl(Y, Au ? Au.options.ghostClass : this.options.ghostClass, !1), Wl(Y, this.options.chosenClass, !1), bu({ + bu = !1, Nu = !1, Mu = !1, clearInterval(this._loopId), clearTimeout(this._dragStartTimer), ld(this.cloneId), ld(this._dragStartId), this.nativeDraggable && (J(document, "drop", this), J(t, "dragstart", this._onDragStart)), this._offMoveEvents(), this._offUpEvents(), wl && Y(document.body, "user-select", ""), Y(X, "transform", ""), e && (ku && (e.cancelable && e.preventDefault(), !n.dropBubble && e.stopPropagation()), Z && Z.parentNode && Z.parentNode.removeChild(Z), (Q === lu || yu && yu.lastPutMode !== "clone") && fu && fu.parentNode && fu.parentNode.removeChild(fu), X && (this.nativeDraggable && J(X, "dragend", this), ed(X), X.style["will-change"] = "", ku && !bu && Ml(X, yu ? yu.options.ghostClass : this.options.ghostClass, !1), Ml(X, this.options.chosenClass, !1), cu({ sortable: this, name: "unchoose", - toEl: xu, + toEl: lu, newIndex: null, newDraggableIndex: null, originalEvent: e - }), Z === xu ? Eu !== Tu && Eu >= 0 && (bu({ + }), Q === lu ? hu !== mu && hu >= 0 && (cu({ sortable: this, name: "update", - toEl: xu, + toEl: lu, originalEvent: e - }), bu({ + }), cu({ sortable: this, name: "sort", - toEl: xu, + toEl: lu, originalEvent: e - })) : (Eu >= 0 && (bu({ - rootEl: xu, + })) : (hu >= 0 && (cu({ + rootEl: lu, name: "add", - toEl: xu, - fromEl: Z, + toEl: lu, + fromEl: Q, originalEvent: e - }), bu({ + }), cu({ sortable: this, name: "remove", - toEl: xu, + toEl: lu, originalEvent: e - }), bu({ - rootEl: xu, + }), cu({ + rootEl: lu, name: "sort", - toEl: xu, - fromEl: Z, + toEl: lu, + fromEl: Q, originalEvent: e - }), bu({ + }), cu({ sortable: this, name: "sort", - toEl: xu, + toEl: lu, originalEvent: e - })), Au && Au.save()), $.active && ((Eu == null || Eu === -1) && (Eu = Tu, Ou = Du), bu({ + })), yu && yu.save()), $.active && ((hu == null || hu === -1) && (hu = mu, _u = gu), cu({ sortable: this, name: "end", - toEl: xu, + toEl: lu, originalEvent: e }), this.save()))), this._nulling(); }, _nulling: function() { - yu("nulling", this), Z = Y = xu = X = Su = Q = Cu = wu = Pu = Fu = Bu = Eu = Ou = Tu = Du = Vu = Hu = Au = ku = $.dragged = $.ghost = $.clone = $.active = null; + su("nulling", this), Q = X = lu = Z = uu = fu = du = pu = Cu = wu = ku = hu = _u = mu = gu = Au = ju = yu = vu = $.dragged = $.ghost = $.clone = $.active = null; var e = this.el; - Yu.forEach(function(t) { + Ru.forEach(function(t) { e.contains(t) && (t.checked = !0); - }), Yu.length = Iu = Lu = 0; + }), Ru.length = Tu = Eu = 0; }, handleEvent: function(e) { switch (e.type) { @@ -6620,20 +6707,20 @@ $.prototype = { break; case "dragenter": case "dragover": - Y && (this._onDragOver(e), ld(e)); + X && (this._onDragOver(e), Qu(e)); break; case "selectstart": e.preventDefault(); } }, toArray: function() { - for (var e = [], t, n = this.el.children, r = 0, i = n.length, a = this.options; r < i; r++) t = n[r], Hl(t, a.draggable, this.el, !1) && e.push(t.getAttribute(a.dataIdAttr) || _d(t)); + for (var e = [], t, n = this.el.children, r = 0, i = n.length, a = this.options; r < i; r++) t = n[r], Al(t, a.draggable, this.el, !1) && e.push(t.getAttribute(a.dataIdAttr) || od(t)); return e; }, sort: function(e, t) { var n = {}, r = this.el; this.toArray().forEach(function(e, t) { var i = r.children[t]; - Hl(i, this.options.draggable, r, !1) && (n[e] = i); + Al(i, this.options.draggable, r, !1) && (n[e] = i); }, this), t && this.captureAnimationState(), e.forEach(function(e) { n[e] && (r.removeChild(n[e]), r.appendChild(n[e])); }), t && this.animateAll(); @@ -6643,25 +6730,25 @@ $.prototype = { e && e.set && e.set(this); }, closest: function(e, t) { - return Hl(e, t || this.options.draggable, this.el, !1); + return Al(e, t || this.options.draggable, this.el, !1); }, option: function(e, t) { var n = this.options; if (t === void 0) return n[e]; - var r = gu.modifyOption(this, e, t); - n[e] = r === void 0 ? t : r, e === "group" && id(n); + var r = iu.modifyOption(this, e, t); + n[e] = r === void 0 ? t : r, e === "group" && qu(n); }, destroy: function() { - yu("destroy", this); + su("destroy", this); var e = this.el; - e[uu] = null, q(e, "mousedown", this._onTapStart), q(e, "touchstart", this._onTapStart), q(e, "pointerdown", this._onTapStart), this.nativeDraggable && (q(e, "dragover", this), q(e, "dragenter", this)), Array.prototype.forEach.call(e.querySelectorAll("[draggable]"), function(e) { + e[Ql] = null, J(e, "mousedown", this._onTapStart), J(e, "touchstart", this._onTapStart), J(e, "pointerdown", this._onTapStart), this.nativeDraggable && (J(e, "dragover", this), J(e, "dragenter", this)), Array.prototype.forEach.call(e.querySelectorAll("[draggable]"), function(e) { e.removeAttribute("draggable"); - }), this._onDrop(), this._disableDelayedDragEvents(), Nu.splice(Nu.indexOf(this.el), 1), this.el = e = null; + }), this._onDrop(), this._disableDelayedDragEvents(), Su.splice(Su.indexOf(this.el), 1), this.el = e = null; }, _hideClone: function() { - if (!wu) { - if (yu("hideClone", this), $.eventCanceled) return; - J(Q, "display", "none"), this.options.removeCloneOnHide && Q.parentNode && Q.parentNode.removeChild(Q), wu = !0; + if (!pu) { + if (su("hideClone", this), $.eventCanceled) return; + Y(fu, "display", "none"), this.options.removeCloneOnHide && fu.parentNode && fu.parentNode.removeChild(fu), pu = !0; } }, _showClone: function(e) { @@ -6669,100 +6756,100 @@ $.prototype = { this._hideClone(); return; } - if (wu) { - if (yu("showClone", this), $.eventCanceled) return; - Y.parentNode == Z && !this.options.group.revertClone ? Z.insertBefore(Q, Y) : Su ? Z.insertBefore(Q, Su) : Z.appendChild(Q), this.options.group.revertClone && this.animate(Y, Q), J(Q, "display", ""), wu = !1; + if (pu) { + if (su("showClone", this), $.eventCanceled) return; + X.parentNode == Q && !this.options.group.revertClone ? Q.insertBefore(fu, X) : uu ? Q.insertBefore(fu, uu) : Q.appendChild(fu), this.options.group.revertClone && this.animate(X, fu), Y(fu, "display", ""), pu = !1; } } }; -function ld(e) { +function Qu(e) { e.dataTransfer && (e.dataTransfer.dropEffect = "move"), e.cancelable && e.preventDefault(); } -function ud(e, t, n, r, i, a, o, s) { - var c, l = e[uu], u = l.options.onMove, d; - return window.CustomEvent && !Nl && !Pl ? c = new CustomEvent("move", { +function $u(e, t, n, r, i, a, o, s) { + var c, l = e[Ql], u = l.options.onMove, d; + return window.CustomEvent && !xl && !Sl ? c = new CustomEvent("move", { bubbles: !0, cancelable: !0 - }) : (c = document.createEvent("Event"), c.initEvent("move", !0, !0)), c.to = t, c.from = e, c.dragged = n, c.draggedRect = r, c.related = i || t, c.relatedRect = a || Jl(t), c.willInsertAfter = s, c.originalEvent = o, e.dispatchEvent(c), u && (d = u.call(l, c, o)), d; + }) : (c = document.createEvent("Event"), c.initEvent("move", !0, !0)), c.to = t, c.from = e, c.dragged = n, c.draggedRect = r, c.related = i || t, c.relatedRect = a || Il(t), c.willInsertAfter = s, c.originalEvent = o, e.dispatchEvent(c), u && (d = u.call(l, c, o)), d; } -function dd(e) { +function ed(e) { e.draggable = !1; } -function fd() { - Ju = !1; +function td() { + Lu = !1; } -function pd(e, t, n) { - var r = Jl(Xl(n.el, 0, n.options, !0)), i = lu(n.el, n.options, X), a = 10; +function nd(e, t, n) { + var r = Il(Rl(n.el, 0, n.options, !0)), i = Zl(n.el, n.options, Z), a = 10; return t ? e.clientX < i.left - a || e.clientY < r.top && e.clientX < r.right : e.clientY < i.top - a || e.clientY < r.bottom && e.clientX < r.left; } -function md(e, t, n) { - var r = Jl(Zl(n.el, n.options.draggable)), i = lu(n.el, n.options, X), a = 10; +function rd(e, t, n) { + var r = Il(zl(n.el, n.options.draggable)), i = Zl(n.el, n.options, Z), a = 10; return t ? e.clientX > i.right + a || e.clientY > r.bottom && e.clientX > r.left : e.clientY > i.bottom + a || e.clientX > r.right && e.clientY > r.top; } -function hd(e, t, n, r, i, a, o, s) { +function id(e, t, n, r, i, a, o, s) { var c = r ? e.clientY : e.clientX, l = r ? n.height : n.width, u = r ? n.top : n.left, d = r ? n.bottom : n.right, f = !1; if (!o) { - if (s && Gu < l * i) { - if (!Uu && (Hu === 1 ? c > u + l * a / 2 : c < d - l * a / 2) && (Uu = !0), Uu) f = !0; - else if (Hu === 1 ? c < u + Gu : c > d - Gu) return -Hu; - } else if (c > u + l * (1 - i) / 2 && c < d - l * (1 - i) / 2) return gd(t); + if (s && Pu < l * i) { + if (!Mu && (ju === 1 ? c > u + l * a / 2 : c < d - l * a / 2) && (Mu = !0), Mu) f = !0; + else if (ju === 1 ? c < u + Pu : c > d - Pu) return -ju; + } else if (c > u + l * (1 - i) / 2 && c < d - l * (1 - i) / 2) return ad(t); } return f ||= o, f && (c < u + l * a / 2 || c > d - l * a / 2) ? c > u + l / 2 ? 1 : -1 : 0; } -function gd(e) { - return Ql(Y) < Ql(e) ? 1 : -1; +function ad(e) { + return Bl(X) < Bl(e) ? 1 : -1; } -function _d(e) { +function od(e) { for (var t = e.tagName + e.className + e.src + e.href + e.textContent, n = t.length, r = 0; n--;) r += t.charCodeAt(n); return r.toString(36); } -function vd(e) { - Yu.length = 0; +function sd(e) { + Ru.length = 0; for (var t = e.getElementsByTagName("input"), n = t.length; n--;) { var r = t[n]; - r.checked && Yu.push(r); + r.checked && Ru.push(r); } } -function yd(e) { +function cd(e) { return setTimeout(e, 0); } -function bd(e) { +function ld(e) { return clearTimeout(e); } -Xu && K(document, "touchmove", function(e) { - ($.active || ju) && e.cancelable && e.preventDefault(); +zu && q(document, "touchmove", function(e) { + ($.active || bu) && e.cancelable && e.preventDefault(); }), $.utils = { - on: K, - off: q, - css: J, - find: Kl, + on: q, + off: J, + css: Y, + find: Pl, is: function(e, t) { - return !!Hl(e, t, e, !1); + return !!Al(e, t, e, !1); }, - extend: nu, - throttle: au, - closest: Hl, - toggleClass: Wl, - clone: cu, - index: Ql, - nextTick: yd, - cancelNextTick: bd, - detectDirection: td, - getChild: Xl, - expando: uu + extend: Wl, + throttle: ql, + closest: Al, + toggleClass: Ml, + clone: Xl, + index: Bl, + nextTick: cd, + cancelNextTick: ld, + detectDirection: Wu, + getChild: Rl, + expando: Ql }, $.get = function(e) { - return e[uu]; + return e[Ql]; }, $.mount = function() { var e = [...arguments]; e[0].constructor === Array && (e = e[0]), e.forEach(function(e) { if (!e.prototype || !e.prototype.constructor) throw `Sortable: Mounted plugin must be a constructor function, not ${{}.toString.call(e)}`; - e.utils && ($.utils = Tl(Tl({}, $.utils), e.utils)), gu.mount(e); + e.utils && ($.utils = pl(pl({}, $.utils), e.utils)), iu.mount(e); }); }, $.create = function(e, t) { return new $(e, t); -}, $.version = jl; -var xd = [], Sd, Cd, wd = !1, Td, Ed, Dd, Od; -function kd() { +}, $.version = yl; +var ud = [], dd, fd, pd = !1, md, hd, gd, _d; +function vd() { function e() { for (var e in this.defaults = { scroll: !0, @@ -6775,70 +6862,70 @@ function kd() { return e.prototype = { dragStarted: function(e) { var t = e.originalEvent; - this.sortable.nativeDraggable ? K(document, "dragover", this._handleAutoScroll) : this.options.supportPointer ? K(document, "pointermove", this._handleFallbackAutoScroll) : t.touches ? K(document, "touchmove", this._handleFallbackAutoScroll) : K(document, "mousemove", this._handleFallbackAutoScroll); + this.sortable.nativeDraggable ? q(document, "dragover", this._handleAutoScroll) : this.options.supportPointer ? q(document, "pointermove", this._handleFallbackAutoScroll) : t.touches ? q(document, "touchmove", this._handleFallbackAutoScroll) : q(document, "mousemove", this._handleFallbackAutoScroll); }, dragOverCompleted: function(e) { var t = e.originalEvent; !this.options.dragOverBubble && !t.rootEl && this._handleAutoScroll(t); }, drop: function() { - this.sortable.nativeDraggable ? q(document, "dragover", this._handleAutoScroll) : (q(document, "pointermove", this._handleFallbackAutoScroll), q(document, "touchmove", this._handleFallbackAutoScroll), q(document, "mousemove", this._handleFallbackAutoScroll)), jd(), Ad(), ou(); + this.sortable.nativeDraggable ? J(document, "dragover", this._handleAutoScroll) : (J(document, "pointermove", this._handleFallbackAutoScroll), J(document, "touchmove", this._handleFallbackAutoScroll), J(document, "mousemove", this._handleFallbackAutoScroll)), bd(), yd(), Jl(); }, nulling: function() { - Dd = Cd = Sd = wd = Od = Td = Ed = null, xd.length = 0; + gd = fd = dd = pd = _d = md = hd = null, ud.length = 0; }, _handleFallbackAutoScroll: function(e) { this._handleAutoScroll(e, !0); }, _handleAutoScroll: function(e, t) { var n = this, r = (e.touches ? e.touches[0] : e).clientX, i = (e.touches ? e.touches[0] : e).clientY, a = document.elementFromPoint(r, i); - if (Dd = e, t || this.options.forceAutoScrollFallback || Pl || Nl || Il) { - Md(e, this.options, a, t); - var o = tu(a, !0); - wd && (!Od || r !== Td || i !== Ed) && (Od && jd(), Od = setInterval(function() { - var a = tu(document.elementFromPoint(r, i), !0); - a !== o && (o = a, Ad()), Md(e, n.options, a, t); - }, 10), Td = r, Ed = i); + if (gd = e, t || this.options.forceAutoScrollFallback || Sl || xl || wl) { + xd(e, this.options, a, t); + var o = Ul(a, !0); + pd && (!_d || r !== md || i !== hd) && (_d && bd(), _d = setInterval(function() { + var a = Ul(document.elementFromPoint(r, i), !0); + a !== o && (o = a, yd()), xd(e, n.options, a, t); + }, 10), md = r, hd = i); } else { - if (!this.options.bubbleScroll || tu(a, !0) === ql()) { - Ad(); + if (!this.options.bubbleScroll || Ul(a, !0) === Fl()) { + yd(); return; } - Md(e, this.options, tu(a, !1), !1); + xd(e, this.options, Ul(a, !1), !1); } } - }, Cl(e, { + }, dl(e, { pluginName: "scroll", initializeByDefault: !0 }); } -function Ad() { - xd.forEach(function(e) { +function yd() { + ud.forEach(function(e) { clearInterval(e.pid); - }), xd = []; + }), ud = []; } -function jd() { - clearInterval(Od); +function bd() { + clearInterval(_d); } -var Md = au(function(e, t, n, r) { +var xd = ql(function(e, t, n, r) { if (t.scroll) { - var i = (e.touches ? e.touches[0] : e).clientX, a = (e.touches ? e.touches[0] : e).clientY, o = t.scrollSensitivity, s = t.scrollSpeed, c = ql(), l = !1, u; - Cd !== n && (Cd = n, Ad(), Sd = t.scroll, u = t.scrollFn, Sd === !0 && (Sd = tu(n, !0))); - var d = 0, f = Sd; + var i = (e.touches ? e.touches[0] : e).clientX, a = (e.touches ? e.touches[0] : e).clientY, o = t.scrollSensitivity, s = t.scrollSpeed, c = Fl(), l = !1, u; + fd !== n && (fd = n, yd(), dd = t.scroll, u = t.scrollFn, dd === !0 && (dd = Ul(n, !0))); + var d = 0, f = dd; do { - var p = f, m = Jl(p), h = m.top, g = m.bottom, _ = m.left, v = m.right, y = m.width, b = m.height, x = void 0, S = void 0, C = p.scrollWidth, w = p.scrollHeight, T = J(p), E = p.scrollLeft, D = p.scrollTop; + var p = f, m = Il(p), h = m.top, g = m.bottom, _ = m.left, v = m.right, y = m.width, b = m.height, x = void 0, S = void 0, C = p.scrollWidth, w = p.scrollHeight, T = Y(p), E = p.scrollLeft, D = p.scrollTop; p === c ? (x = y < C && (T.overflowX === "auto" || T.overflowX === "scroll" || T.overflowX === "visible"), S = b < w && (T.overflowY === "auto" || T.overflowY === "scroll" || T.overflowY === "visible")) : (x = y < C && (T.overflowX === "auto" || T.overflowX === "scroll"), S = b < w && (T.overflowY === "auto" || T.overflowY === "scroll")); var O = x && (Math.abs(v - i) <= o && E + y < C) - (Math.abs(_ - i) <= o && !!E), k = S && (Math.abs(g - a) <= o && D + b < w) - (Math.abs(h - a) <= o && !!D); - if (!xd[d]) for (var A = 0; A <= d; A++) xd[A] || (xd[A] = {}); - (xd[d].vx != O || xd[d].vy != k || xd[d].el !== p) && (xd[d].el = p, xd[d].vx = O, xd[d].vy = k, clearInterval(xd[d].pid), (O != 0 || k != 0) && (l = !0, xd[d].pid = setInterval(function() { - r && this.layer === 0 && $.active._onTouchMove(Dd); - var t = xd[this.layer].vy ? xd[this.layer].vy * s : 0, n = xd[this.layer].vx ? xd[this.layer].vx * s : 0; - (typeof u != "function" || u.call($.dragged.parentNode[uu], n, t, e, Dd, xd[this.layer].el) === "continue") && su(xd[this.layer].el, n, t); + if (!ud[d]) for (var A = 0; A <= d; A++) ud[A] || (ud[A] = {}); + (ud[d].vx != O || ud[d].vy != k || ud[d].el !== p) && (ud[d].el = p, ud[d].vx = O, ud[d].vy = k, clearInterval(ud[d].pid), (O != 0 || k != 0) && (l = !0, ud[d].pid = setInterval(function() { + r && this.layer === 0 && $.active._onTouchMove(gd); + var t = ud[this.layer].vy ? ud[this.layer].vy * s : 0, n = ud[this.layer].vx ? ud[this.layer].vx * s : 0; + (typeof u != "function" || u.call($.dragged.parentNode[Ql], n, t, e, gd, ud[this.layer].el) === "continue") && Yl(ud[this.layer].el, n, t); }.bind({ layer: d }), 24))), d++; - } while (t.bubbleScroll && f !== c && (f = tu(f, !1))); - wd = l; + } while (t.bubbleScroll && f !== c && (f = Ul(f, !1))); + pd = l; } -}, 30), Nd = function(e) { +}, 30), Sd = function(e) { var t = e.originalEvent, n = e.putSortable, r = e.dragEl, i = e.activeSortable, a = e.dispatchSortableEvent, o = e.hideGhostForTarget, s = e.unhideGhostForTarget; if (t) { var c = n || i; @@ -6850,8 +6937,8 @@ var Md = au(function(e, t, n, r) { })); } }; -function Pd() {} -Pd.prototype = { +function Cd() {} +Cd.prototype = { startIndex: null, dragStart: function(e) { var t = e.oldDraggableIndex; @@ -6860,28 +6947,28 @@ Pd.prototype = { onSpill: function(e) { var t = e.dragEl, n = e.putSortable; this.sortable.captureAnimationState(), n && n.captureAnimationState(); - var r = Xl(this.sortable.el, this.startIndex, this.options); + var r = Rl(this.sortable.el, this.startIndex, this.options); r ? this.sortable.el.insertBefore(t, r) : this.sortable.el.appendChild(t), this.sortable.animateAll(), n && n.animateAll(); }, - drop: Nd -}, Cl(Pd, { pluginName: "revertOnSpill" }); -function Fd() {} -Fd.prototype = { + drop: Sd +}, dl(Cd, { pluginName: "revertOnSpill" }); +function wd() {} +wd.prototype = { onSpill: function(e) { var t = e.dragEl, n = e.putSortable || this.sortable; n.captureAnimationState(), t.parentNode && t.parentNode.removeChild(t), n.animateAll(); }, - drop: Nd -}, Cl(Fd, { pluginName: "removeOnSpill" }), $.mount(new kd()), $.mount(Fd, Pd); + drop: Sd +}, dl(wd, { pluginName: "removeOnSpill" }), $.mount(new vd()), $.mount(wd, Cd); //#endregion //#region resources/js/components/TaskCard.vue?vue&type=script&setup=true&lang.ts -var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "text-sm font-medium text-heading" }, Rd = { class: "mt-2 flex flex-wrap items-center gap-2 text-xs text-muted" }, zd = ["title"], Bd = { class: "mt-3 flex items-center justify-between gap-2" }, Vd = { +var Td = { class: "flex items-start justify-between gap-2" }, Ed = { class: "text-sm font-medium text-heading" }, Dd = { class: "mt-2 flex flex-wrap items-center gap-2 text-xs text-muted" }, Od = ["title"], kd = { class: "mt-3 flex items-center justify-between gap-2" }, Ad = { key: 0, class: "text-xs tabular-nums text-muted" -}, Hd = { class: "mt-2 flex items-center justify-between" }, Ud = { +}, jd = { class: "mt-2 flex items-center justify-between" }, Md = { key: 1, class: "text-xs text-subtle" -}, Wd = ["title"], Gd = /* @__PURE__ */ l({ +}, Nd = ["title"], Pd = /* @__PURE__ */ l({ __name: "TaskCard", props: { client: {}, @@ -6897,7 +6984,7 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex NORMAL: "bg-primary-50 text-primary-500", HIGH: "bg-alert-warning-bg text-alert-warning-text", URGENT: "bg-alert-error-bg text-alert-error-text" - }, u = V(), d = n(() => Va(r.task)), p = n(() => r.projects.find((e) => e.id === r.task.project_id)), m = n(() => r.task.project_id === null ? null : p.value?.identifier || p.value?.name || null), h = n(() => [p.value?.name, Zn(r.task.customer_id)].filter(Boolean).join(" · ")), g = n(() => r.members.find((e) => e.id === r.task.assignee_id)), v = n(() => r.task.assignee_id === null ? null : g.value ? ye(g.value.name) : `#${r.task.assignee_id}`), y = n(() => g.value?.name ?? (r.task.assignee_id === null ? u("tasks_projects.tasks.unassigned") : `#${r.task.assignee_id}`)), b = n(() => qa(d.value.logged_minutes)); + }, u = B(), d = n(() => nt(r.task)), p = n(() => r.projects.find((e) => e.id === r.task.project_id)), m = n(() => r.task.project_id === null ? null : p.value?.identifier || p.value?.name || null), h = n(() => [p.value?.name, $t(r.task.customer_id)].filter(Boolean).join(" · ")), g = n(() => r.members.find((e) => e.id === r.task.assignee_id)), v = n(() => r.task.assignee_id === null ? null : g.value ? pt(g.value.name) : `#${r.task.assignee_id}`), y = n(() => g.value?.name ?? (r.task.assignee_id === null ? u("tasks_projects.tasks.unassigned") : `#${r.task.assignee_id}`)), b = n(() => Pa(d.value.logged_minutes)); function x(e) { return u(`tasks_projects.tasks.priority.${e.toLowerCase()}`); } @@ -6905,20 +6992,20 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex class: "cursor-pointer rounded-lg border border-line-default bg-surface p-3 shadow-sm hover:bg-hover", onClick: n[1] ||= (t) => s("open", e.task) }, [ - o("div", Id, [o("p", Ld, S(e.task.name), 1), e.task.priority ? (_(), a("span", { + o("div", Td, [o("p", Ed, S(e.task.name), 1), e.task.priority ? (_(), a("span", { key: 0, class: f(["shrink-0 rounded-full px-2 py-0.5 text-[11px] font-medium", l[e.task.priority]]) }, S(x(e.task.priority)), 3)) : i("", !0)]), - o("div", Rd, [ + o("div", Dd, [ o("span", null, "#" + S(e.task.number), 1), m.value ? (_(), a("span", { key: 0, class: "rounded-sm bg-surface-tertiary px-1.5 py-0.5 text-[11px] text-body", title: h.value - }, S(m.value), 9, zd)) : i("", !0), - c(Vi, { state: d.value.invoiced }, null, 8, ["state"]) + }, S(m.value), 9, Od)) : i("", !0), + c(da, { state: d.value.invoiced }, null, 8, ["state"]) ]), - o("div", Bd, [c(Oo, { + o("div", kd, [c(ho, { client: e.client, notify: e.notify, task: e.task, @@ -6929,34 +7016,34 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex "notify", "task", "members" - ]), d.value.logged_minutes > 0 ? (_(), a("span", Vd, S(b.value), 1)) : i("", !0)]), - o("div", Hd, [e.task.due_date ? (_(), a("span", { + ]), d.value.logged_minutes > 0 ? (_(), a("span", Ad, S(b.value), 1)) : i("", !0)]), + o("div", jd, [e.task.due_date ? (_(), a("span", { key: 0, - class: f(["text-xs", C(be)(e.task.due_date) && !e.task.closed_at ? "font-medium text-status-red" : "text-muted"]) - }, S(C(ge)(e.task.due_date)), 3)) : (_(), a("span", Ud, "-")), v.value ? (_(), a("span", { + class: f(["text-xs", C(mt)(e.task.due_date) && !e.task.closed_at ? "font-medium text-status-red" : "text-muted"]) + }, S(C(ut)(e.task.due_date)), 3)) : (_(), a("span", Md, "-")), v.value ? (_(), a("span", { key: 2, class: "flex h-6 w-6 items-center justify-center rounded-full bg-primary-50 text-[11px] font-semibold text-primary-500", title: y.value - }, S(v.value), 9, Wd)) : i("", !0)]) + }, S(v.value), 9, Nd)) : i("", !0)]) ])); } -}), Kd = { class: "mt-4" }, qd = { +}), Fd = { class: "mt-4" }, Id = { key: 0, class: "mb-3 text-xs text-subtle" -}, Jd = { +}, Ld = { key: 1, class: "flex justify-center py-16" -}, Yd = { +}, Rd = { key: 3, class: "flex items-start gap-4 overflow-x-auto pb-4" -}, Xd = { class: "flex items-center justify-between border-b border-line-light px-3 py-2.5" }, Zd = { class: "flex items-center" }, Qd = { class: "text-sm font-semibold text-heading" }, $d = { class: "ml-2 text-xs text-muted" }, ef = [ +}, zd = { class: "flex items-center justify-between border-b border-line-light px-3 py-2.5" }, Bd = { class: "flex items-center" }, Vd = { class: "text-sm font-semibold text-heading" }, Hd = { class: "ml-2 text-xs text-muted" }, Ud = [ "aria-label", "title", "onClick" -], tf = ["data-status-id"], nf = { +], Wd = ["data-status-id"], Gd = { key: 0, class: "px-3 pt-2 text-xs text-subtle" -}, rf = { class: "px-3 pt-2 pb-3" }, af = ["onClick"], of = /* @__PURE__ */ l({ +}, Kd = { class: "px-3 pt-2 pb-3" }, qd = ["onClick"], Jd = /* @__PURE__ */ l({ __name: "TasksBoardView", props: { client: { type: [Function, Object] }, @@ -6967,27 +7054,27 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex projects: {} }, setup(t, { expose: s }) { - let l = t, u = V(), d = y([]), h = y(!0), g = y(!1), v = y(null), w = y({}), T = /* @__PURE__ */ new Map(), O = /* @__PURE__ */ new Map(), k = !1, A = n(() => l.projects.map((e) => ({ + let l = t, u = B(), d = y([]), h = y(!0), g = y(!1), v = y(null), w = y({}), T = /* @__PURE__ */ new Map(), O = /* @__PURE__ */ new Map(), k = !1, A = n(() => l.projects.map((e) => ({ id: e.id, label: e.name }))), j = n(() => !h.value && d.value.length === 0), M = n(() => xa.settings.hide_invoiced_on_board); function N(e) { return (e.tasks ?? []).filter((e) => { - let t = Va(e).invoiced; - return M.value && t === "invoiced" ? !1 : mi(l.filters.status) ? l.filters.status === "invoiced" ? t === "invoiced" : t !== "invoiced" : !0; + let t = nt(e).invoiced; + return M.value && t === "invoiced" ? !1 : zi(l.filters.status) ? l.filters.status === "invoiced" ? t === "invoiced" : t !== "invoiced" : !0; }); } - E(() => `${l.filters.project}|${l.filters.user}`, () => void P(), { immediate: !0 }), E(za, () => void P()), m(() => { + E(() => `${l.filters.project}|${l.filters.user}`, () => void P(), { immediate: !0 }), E(et, () => void P()), m(() => { for (let e of T.values()) e.destroy(); T.clear(), O.clear(); }); async function P() { - let e = {}, t = xi(l.filters.project), n = xi(l.filters.user); + let e = {}, t = Ki(l.filters.project), n = Ki(l.filters.user); t !== null && (e.project_id = t), n !== null && (e.assignee_id = n), h.value = !0; try { - d.value = await Tn(l.client, e), d.value.some((e) => e.tasks.some((e) => e.customer_id !== null)) && Qn(l.client); + d.value = await ar(l.client, e), d.value.some((e) => e.tasks.some((e) => e.customer_id !== null)) && en(l.client); } catch (e) { - l.notify("error", z(e, u("tasks_projects.board.load_failed"))); + l.notify("error", H(e, u("tasks_projects.board.load_failed"))); } finally { h.value = !1; } @@ -7003,7 +7090,7 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex k = !0; }, onEnd: (e) => { - ee(e), setTimeout(() => { + R(e), setTimeout(() => { k = !1; }); } @@ -7016,7 +7103,7 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex function L(e) { return d.value.find((t) => t.status.id === e); } - async function ee(e) { + async function R(e) { let t = Number(e.from.dataset.statusId), n = Number(e.to.dataset.statusId), r = e.oldIndex ?? 0, i = e.newIndex ?? 0; if (I(e), Number.isNaN(t) || Number.isNaN(n) || t === n && r === i) return; let a = L(t), o = L(n); @@ -7031,7 +7118,7 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex let f = N(o), p = f[i - 1] ?? null, m = f[i] ?? null, h = p === null ? 0 : o.tasks.findIndex((e) => e.id === p.id) + 1; o.tasks.splice(h, 0, s); try { - let e = await In(l.client, s.id, { + let e = await gr(l.client, s.id, { task_status_id: n, before_id: p?.id ?? null, after_id: m?.id ?? null @@ -7041,31 +7128,31 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex status: o.status.name })); } catch (e) { - a.tasks = d.from, o.tasks = d.to, l.notify("error", z(e, u("tasks_projects.board.move_failed"))); + a.tasks = d.from, o.tasks = d.to, l.notify("error", H(e, u("tasks_projects.board.move_failed"))); } } - function R(e) { + function z(e) { let t = e ?? l.statuses.find((e) => e.is_default) ?? l.statuses[0]; v.value = null, w.value = { task_status_id: t?.id ?? null, - project_id: xi(l.filters.project) + project_id: Ki(l.filters.project) }, g.value = !0; } - function te(e) { + function ee(e) { k || (v.value = e, w.value = {}, g.value = !0); } - function ne(e) { + function te(e) { let t = v.value ? u("tasks_projects.tasks.updated", { name: e.name }) : u("tasks_projects.tasks.created", { name: e.name }); - g.value = !1, v.value = null, l.notify("success", t), U(); + g.value = !1, v.value = null, l.notify("success", t), V(); } - function re(e) { - g.value = !1, v.value = null, l.notify("success", u("tasks_projects.tasks.deleted", { name: e.name })), U(); + function ne(e) { + g.value = !1, v.value = null, l.notify("success", u("tasks_projects.tasks.deleted", { name: e.name })), V(); } - return s({ openCreate: () => R(null) }), (n, s) => { + return s({ openCreate: () => z(null) }), (n, s) => { let l = x("BaseSpinner"), m = x("BaseIcon"), y = x("BaseEmptyPlaceholder"); - return _(), a("section", Kd, [ - M.value ? (_(), a("p", qd, S(C(u)("tasks_projects.board.hidden_invoiced")), 1)) : i("", !0), - h.value && d.value.length === 0 ? (_(), a("div", Jd, [c(l, { class: "h-8 w-8 text-primary-500" })])) : j.value ? (_(), r(y, { + return _(), a("section", Fd, [ + M.value ? (_(), a("p", Id, S(C(u)("tasks_projects.board.hidden_invoiced")), 1)) : i("", !0), + h.value && d.value.length === 0 ? (_(), a("div", Ld, [c(l, { class: "h-8 w-8 text-primary-500" })])) : j.value ? (_(), r(y, { key: 2, title: C(u)("tasks_projects.task_statuses.none"), description: C(u)("tasks_projects.tasks.empty_description") @@ -7075,33 +7162,33 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex class: "mt-5 mb-4 h-16 w-16 text-subtle" })]), _: 1 - }, 8, ["title", "description"])) : (_(), a("div", Yd, [(_(!0), a(e, null, b(d.value, (n) => (_(), a("section", { + }, 8, ["title", "description"])) : (_(), a("div", Rd, [(_(!0), a(e, null, b(d.value, (n) => (_(), a("section", { key: n.status.id, - class: "w-72 shrink-0 rounded-xl border border-line-default bg-surface-secondary" + class: "w-64 shrink-0 rounded-xl border border-line-default bg-surface-secondary" }, [ - o("header", Xd, [o("div", Zd, [ + o("header", zd, [o("div", Bd, [ o("span", { class: f(["mr-2 inline-block h-2.5 w-2.5 shrink-0 rounded-full", n.status.colour ? "" : "bg-line-default"]), style: p(n.status.colour ? { backgroundColor: n.status.colour } : void 0) }, null, 6), - o("h3", Qd, S(n.status.name), 1), - o("span", $d, S(N(n).length), 1) + o("h3", Vd, S(n.status.name), 1), + o("span", Hd, S(N(n).length), 1) ]), o("button", { type: "button", class: "rounded-md p-1 text-subtle hover:bg-hover hover:text-body", "aria-label": C(u)("tasks_projects.tasks.new_task"), title: C(u)("tasks_projects.tasks.new_task"), - onClick: (e) => R(n.status) + onClick: (e) => z(n.status) }, [c(m, { name: "PlusIcon", class: "h-4 w-4" - })], 8, ef)]), + })], 8, Ud)]), o("div", { ref_for: !0, ref: (e) => F(n.status.id, e), "data-status-id": n.status.id, class: "min-h-20 space-y-2 px-3 pt-3" - }, [(_(!0), a(e, null, b(N(n), (e) => (_(), r(Gd, { + }, [(_(!0), a(e, null, b(N(n), (e) => (_(), r(Pd, { key: e.id, "data-task-id": e.id, client: t.client, @@ -7109,7 +7196,7 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex task: e, projects: t.projects, members: t.members, - onOpen: te + onOpen: ee }, null, 8, [ "data-task-id", "client", @@ -7117,15 +7204,15 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex "task", "projects", "members" - ]))), 128))], 8, tf), - N(n).length === 0 ? (_(), a("p", nf, S(C(u)("tasks_projects.board.empty_column")), 1)) : i("", !0), - o("div", rf, [o("button", { + ]))), 128))], 8, Wd), + N(n).length === 0 ? (_(), a("p", Gd, S(C(u)("tasks_projects.board.empty_column")), 1)) : i("", !0), + o("div", Kd, [o("button", { type: "button", class: "w-full rounded-md border border-dashed border-line-default py-1.5 text-xs text-muted hover:bg-hover hover:text-body", - onClick: (e) => R(n.status) - }, " + " + S(C(u)("tasks_projects.tasks.new_task")), 9, af)]) + onClick: (e) => z(n.status) + }, " + " + S(C(u)("tasks_projects.tasks.new_task")), 9, qd)]) ]))), 128))])), - c(Yi, { + c(ya, { show: g.value, client: t.client, notify: t.notify, @@ -7136,8 +7223,8 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex defaults: w.value, compact: v.value === null, onClose: s[0] ||= (e) => g.value = !1, - onSaved: ne, - onDeleted: re + onSaved: te, + onDeleted: ne }, null, 8, [ "show", "client", @@ -7152,11 +7239,12 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex ]); }; } -}), sf = /* @__PURE__ */ l({ +}), Yd = /* @__PURE__ */ l({ __name: "TasksListView", props: { client: { type: [Function, Object] }, notify: { type: Function }, + router: {}, filters: {}, statuses: {}, members: {}, @@ -7164,11 +7252,12 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex }, setup(e, { expose: t }) { let n = y(null); - return t({ openCreate: () => n.value?.openCreate() }), (t, i) => (_(), r(Io, { + return t({ openCreate: () => n.value?.openCreate() }), (t, i) => (_(), r(wo, { ref_key: "listRef", ref: n, client: e.client, notify: e.notify, + router: e.router, filters: e.filters, statuses: e.statuses, members: e.members, @@ -7176,16 +7265,17 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex }, null, 8, [ "client", "notify", + "router", "filters", "statuses", "members", "projects" ])); } -}), cf = { class: "relative table-container" }, lf = { class: "block max-w-64 truncate" }, uf = { class: "tabular-nums" }, df = { +}), Xd = { class: "relative table-container" }, Zd = { class: "block max-w-64 truncate" }, Qd = { class: "tabular-nums" }, $d = { key: 1, class: "text-subtle" -}, ff = /* @__PURE__ */ l({ +}, ef = /* @__PURE__ */ l({ __name: "AllTimeTable", props: { client: { type: [Function, Object] }, @@ -7197,7 +7287,7 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex }, emits: ["edit", "delete"], setup(e, { emit: t }) { - let l = e, u = t, d = V(), p = y(null), m = v({ + let l = e, u = t, d = B(), p = y(null), m = v({ from: "", to: "", billing: "ALL" @@ -7274,10 +7364,10 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex m.from = "", m.to = "", m.billing = "ALL"; } function k(e) { - m.from = e ? _e(e) : ""; + m.from = e ? dt(e) : ""; } function A(e) { - m.to = e ? _e(e) : ""; + m.to = e ? dt(e) : ""; } function j(e) { let t = l.members.find((t) => t.id === e); @@ -7290,13 +7380,13 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex }; l.memberId !== null && (t.user_id = l.memberId), l.projectId !== null && (t.project_id = l.projectId), m.from !== "" && (t.from = m.from), m.to !== "" && (t.to = m.to), m.billing !== "ALL" && (t.billed = m.billing === "BILLED"); try { - let e = await na(l.client, t), n = e.data ?? []; - return Ra(l.client, n.map((e) => e.task_id).filter((e) => typeof e == "number")), { + let e = await De(l.client, t), n = e.data ?? []; + return $e(l.client, n.map((e) => e.task_id).filter((e) => typeof e == "number")), { data: n, pagination: N(e.meta, n.length) }; } catch (e) { - return l.notify("error", z(e, d("tasks_projects.time.load_failed"))), { + return l.notify("error", H(e, d("tasks_projects.time.load_failed"))), { data: [], pagination: N(null, 0) }; @@ -7354,18 +7444,18 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex }, 8, ["label"]) ]), _: 1 - }), o("div", cf, [c(F, { + }), o("div", Xd, [c(F, { ref_key: "tableRef", ref: p, data: M, columns: b.value, class: "mt-3" }, { - "cell-date": D(({ row: e }) => [s(S(C(ge)(C(Ya)(e.data.started_at))), 1)]), + "cell-date": D(({ row: e }) => [s(S(C(ut)(C(Ia)(e.data.started_at))), 1)]), "cell-member": D(({ row: e }) => [s(S(j(e.data.user_id)), 1)]), - "cell-task": D(({ row: e }) => [s(S(C(Ia)(e.data.task_id)), 1)]), - "cell-description": D(({ row: e }) => [o("span", lf, S(e.data.description || "-"), 1)]), - "cell-duration": D(({ row: e }) => [o("span", uf, S(C(qa)(e.data.duration_minutes)), 1)]), + "cell-task": D(({ row: e }) => [s(S(C(Ze)(e.data.task_id)), 1)]), + "cell-description": D(({ row: e }) => [o("span", Zd, S(e.data.description || "-"), 1)]), + "cell-duration": D(({ row: e }) => [o("span", Qd, S(C(Pa)(e.data.duration_minutes)), 1)]), "cell-billable": D(({ row: e }) => [c(w, { class: f(["rounded-full", e.data.billable ? "bg-primary-50! text-primary-500!" : "bg-surface-tertiary! text-muted!"]) }, { default: D(() => [s(S(e.data.billable ? C(d)("tasks_projects.time.billable") : C(d)("tasks_projects.time.non_billable")), 1)]), _: 2 @@ -7373,7 +7463,7 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex "cell-amount": D(({ row: e }) => [e.data.billable ? (_(), r(T, { key: 0, amount: e.data.amount - }, null, 8, ["amount"])) : (_(), a("span", df, "-"))]), + }, null, 8, ["amount"])) : (_(), a("span", $d, "-"))]), "cell-actions": D(({ row: e }) => [c(P, null, { activator: D(() => [c(E, { name: "EllipsisHorizontalIcon", @@ -7401,25 +7491,25 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex }, 8, ["columns"])])]); }; } -}), pf = { class: "mt-4 flex flex-wrap items-center justify-between gap-3" }, mf = { class: "flex items-center gap-2" }, hf = { class: "ml-1 text-sm text-muted" }, gf = { class: "flex items-center gap-2 text-sm" }, _f = { class: "text-muted" }, vf = { class: "text-lg font-semibold tabular-nums text-heading" }, yf = { +}), tf = { class: "mt-4 flex flex-wrap items-center justify-between gap-3" }, nf = { class: "flex items-center gap-2" }, rf = { class: "ml-1 text-sm text-muted" }, af = { class: "flex items-center gap-2 text-sm" }, of = { class: "text-muted" }, sf = { class: "text-lg font-semibold tabular-nums text-heading" }, cf = { key: 0, class: "mt-6 text-sm text-muted" -}, bf = { +}, lf = { key: 1, class: "mt-4 grid gap-3 sm:grid-cols-2 lg:grid-cols-4 xl:grid-cols-7" -}, xf = { class: "flex items-baseline justify-between" }, Sf = { class: "text-xs font-semibold tracking-wide text-heading uppercase" }, Cf = { class: "text-xs text-muted" }, wf = { class: "text-sm font-medium tabular-nums text-heading" }, Tf = { class: "mt-3 flex-1 space-y-2" }, Ef = ["onClick"], Df = { class: "flex items-center justify-between gap-2" }, Of = { class: "truncate text-xs font-medium text-heading" }, kf = { class: "shrink-0 text-xs tabular-nums text-muted" }, Af = { +}, uf = { class: "flex items-baseline justify-between" }, df = { class: "text-xs font-semibold tracking-wide text-heading uppercase" }, ff = { class: "text-xs text-muted" }, pf = { class: "text-sm font-medium tabular-nums text-heading" }, mf = { class: "mt-3 flex-1 space-y-2" }, hf = ["onClick"], gf = { class: "flex items-center justify-between gap-2" }, _f = { class: "truncate text-xs font-medium text-heading" }, vf = { class: "shrink-0 text-xs tabular-nums text-muted" }, yf = { key: 0, class: "mt-1 block truncate text-xs text-muted" -}, jf = { class: "mt-1 flex items-center gap-1" }, Mf = { class: "text-[11px] text-subtle" }, Nf = { +}, bf = { class: "mt-1 flex items-center gap-1" }, xf = { class: "text-[11px] text-subtle" }, Sf = { key: 0, class: "text-[11px] text-subtle" -}, Pf = { +}, Cf = { key: 0, class: "py-2 text-xs text-subtle" -}, Ff = ["onClick"], If = { +}, wf = ["onClick"], Tf = { key: 2, class: "mt-4 text-center text-sm text-subtle" -}, Lf = /* @__PURE__ */ l({ +}, Ef = /* @__PURE__ */ l({ __name: "WeekTimesheet", props: { client: { type: [Function, Object] }, @@ -7431,22 +7521,22 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex }, emits: ["add", "edit"], setup(t, { emit: l }) { - let u = t, d = l, p = V(), m = y($a(/* @__PURE__ */ new Date(), u.weekStart)), h = y([]), g = y(!1), v = n(() => eo(m.value)), w = n(() => { + let u = t, d = l, p = B(), m = y(Ba(/* @__PURE__ */ new Date(), u.weekStart)), h = y([]), g = y(!1), v = n(() => Va(m.value)), w = n(() => { let e = v.value[0], t = v.value[v.value.length - 1]; - return `${ro(e).day} - ${ro(t).day}`; + return `${Wa(e).day} - ${Wa(t).day}`; }), T = n(() => v.value.map((e) => { - let t = no(e), n = h.value.filter((e) => Ya(e.started_at) === t), r = ro(e); + let t = Ua(e), n = h.value.filter((e) => Ia(e.started_at) === t), r = Wa(e); return { key: t, weekday: r.weekday, day: r.day, - today: io(e), + today: Ga(e), entries: n, minutes: A(n) }; })), O = n(() => A(h.value)), k = n(() => !g.value && h.value.length === 0); E(() => u.weekStart, (e) => { - m.value = $a(m.value, e); + m.value = Ba(m.value, e); }), E([ m, () => u.userId, @@ -7465,28 +7555,28 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex try { let e = { user_id: u.userId, - from: no(v.value[0]), - to: no(v.value[v.value.length - 1]) + from: Ua(v.value[0]), + to: Ua(v.value[v.value.length - 1]) }; u.projectId && (e.project_id = u.projectId); - let t = await ra(u.client, e); - h.value = t, Ra(u.client, t.map((e) => e.task_id).filter((e) => typeof e == "number")); + let t = await Oe(u.client, e); + h.value = t, $e(u.client, t.map((e) => e.task_id).filter((e) => typeof e == "number")); } catch (e) { - h.value = [], u.notify("error", z(e, p("tasks_projects.time.load_failed"))); + h.value = [], u.notify("error", H(e, p("tasks_projects.time.load_failed"))); } finally { g.value = !1; } } function M(e) { - m.value = to(m.value, e * 7); + m.value = Ha(m.value, e * 7); } function N() { - m.value = $a(/* @__PURE__ */ new Date(), u.weekStart); + m.value = Ba(/* @__PURE__ */ new Date(), u.weekStart); } return (n, l) => { let u = x("BaseIcon"), m = x("BaseButton"), h = x("BaseSpinner"); return _(), a("section", null, [ - o("header", pf, [o("div", mf, [ + o("header", tf, [o("div", nf, [ c(m, { variant: "white", size: "sm", @@ -7519,33 +7609,33 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex })]), _: 1 }, 8, ["title"]), - o("span", hf, S(w.value), 1) - ]), o("div", gf, [ - o("span", _f, S(C(p)("tasks_projects.time.week_total")), 1), - o("span", vf, S(C(qa)(O.value)), 1), + o("span", rf, S(w.value), 1) + ]), o("div", af, [ + o("span", of, S(C(p)("tasks_projects.time.week_total")), 1), + o("span", sf, S(C(Pa)(O.value)), 1), g.value ? (_(), r(h, { key: 0, class: "h-4 w-4 text-primary-500" })) : i("", !0) ])]), - t.userId === null ? (_(), a("p", yf, S(C(p)("tasks_projects.time.unknown_user")), 1)) : (_(), a("div", bf, [(_(!0), a(e, null, b(T.value, (t) => (_(), a("article", { + t.userId === null ? (_(), a("p", cf, S(C(p)("tasks_projects.time.unknown_user")), 1)) : (_(), a("div", lf, [(_(!0), a(e, null, b(T.value, (t) => (_(), a("article", { key: t.key, class: f(["flex min-h-40 flex-col rounded-xl border bg-surface p-3", t.today ? "border-primary-400" : "border-line-default"]) }, [ - o("header", xf, [o("div", null, [o("p", Sf, S(t.weekday), 1), o("p", Cf, S(t.day), 1)]), o("span", wf, S(C(qa)(t.minutes)), 1)]), - o("ul", Tf, [(_(!0), a(e, null, b(t.entries, (e) => (_(), a("li", { key: e.id }, [o("button", { + o("header", uf, [o("div", null, [o("p", df, S(t.weekday), 1), o("p", ff, S(t.day), 1)]), o("span", pf, S(C(Pa)(t.minutes)), 1)]), + o("ul", mf, [(_(!0), a(e, null, b(t.entries, (e) => (_(), a("li", { key: e.id }, [o("button", { type: "button", class: "w-full rounded-md border border-line-light px-2 py-2 text-left hover:bg-hover", onClick: (t) => d("edit", e) }, [ - o("span", Df, [o("span", Of, S(C(Ia)(e.task_id)), 1), o("span", kf, S(C(qa)(e.duration_minutes)), 1)]), - e.description ? (_(), a("span", Af, S(e.description), 1)) : i("", !0), - o("span", jf, [ + o("span", gf, [o("span", _f, S(C(Ze)(e.task_id)), 1), o("span", vf, S(C(Pa)(e.duration_minutes)), 1)]), + e.description ? (_(), a("span", yf, S(e.description), 1)) : i("", !0), + o("span", bf, [ o("span", { class: f(["inline-block h-1.5 w-1.5 rounded-full", e.billable ? "bg-status-green" : "bg-line-strong"]) }, null, 2), - o("span", Mf, S(e.billable ? C(p)("tasks_projects.time.billable") : C(p)("tasks_projects.time.non_billable")), 1), - e.invoice_id === null ? i("", !0) : (_(), a("span", Nf, " - " + S(C(p)("tasks_projects.time.billed")), 1)) + o("span", xf, S(e.billable ? C(p)("tasks_projects.time.billable") : C(p)("tasks_projects.time.non_billable")), 1), + e.invoice_id === null ? i("", !0) : (_(), a("span", Sf, " - " + S(C(p)("tasks_projects.time.billed")), 1)) ]) - ], 8, Ef)]))), 128)), t.entries.length === 0 ? (_(), a("li", Pf, S(C(p)("tasks_projects.time.no_entries")), 1)) : i("", !0)]), + ], 8, hf)]))), 128)), t.entries.length === 0 ? (_(), a("li", Cf, S(C(p)("tasks_projects.time.no_entries")), 1)) : i("", !0)]), o("button", { type: "button", class: "mt-2 flex items-center justify-center gap-1 rounded-md border border-dashed border-line-default py-1.5 text-xs text-muted hover:bg-hover hover:text-heading", @@ -7553,16 +7643,16 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex }, [c(u, { name: "PlusIcon", class: "h-4 w-4" - }), s(" " + S(C(p)("tasks_projects.time.add_entry")), 1)], 8, Ff) + }), s(" " + S(C(p)("tasks_projects.time.add_entry")), 1)], 8, wf) ], 2))), 128))])), - k.value && t.userId !== null ? (_(), a("p", If, S(C(p)("tasks_projects.time.empty_description")), 1)) : i("", !0) + k.value && t.userId !== null ? (_(), a("p", Tf, S(C(p)("tasks_projects.time.empty_description")), 1)) : i("", !0) ]); }; } -}), Rf = { +}), Df = { key: 0, class: "mt-4 flex gap-6 border-b border-line-default" -}, zf = 5, Bf = /* @__PURE__ */ l({ +}, Of = 5, kf = /* @__PURE__ */ l({ __name: "TasksWeekView", props: { client: { type: [Function, Object] }, @@ -7573,8 +7663,8 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex projects: {} }, setup(e) { - let t = e, s = V(), l = y("MINE"), u = y(!1), d = y(!1), p = y(null), m = y(no(/* @__PURE__ */ new Date())), g = y(0), v = n(() => xa.settings.week_start), b = n(() => xi(t.filters.project)), x = n(() => xi(t.filters.user) ?? xa.userId); - h(() => void w()), E(za, () => { + let t = e, s = B(), l = y("MINE"), u = y(!1), d = y(!1), p = y(null), m = y(Ua(/* @__PURE__ */ new Date())), g = y(0), v = n(() => xa.settings.week_start), b = n(() => Ki(t.filters.project)), x = n(() => Ki(t.filters.user) ?? xa.userId); + h(() => void w()), E(et, () => { g.value += 1; }); async function w() { @@ -7582,36 +7672,36 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex } async function T() { try { - return ((await na(t.client, { limit: zf })).data ?? []).some((e) => e.user_id !== xa.userId); + return ((await De(t.client, { limit: Of })).data ?? []).some((e) => e.user_id !== xa.userId); } catch { return !1; } } function D(e) { - p.value = null, m.value = e ?? no(/* @__PURE__ */ new Date()), d.value = !0; + p.value = null, m.value = e ?? Ua(/* @__PURE__ */ new Date()), d.value = !0; } function O(e) { p.value = e, d.value = !0; } function k() { let e = p.value ? s("tasks_projects.time.updated") : s("tasks_projects.time.created"); - d.value = !1, p.value = null, t.notify("success", e), g.value += 1, U(); + d.value = !1, p.value = null, t.notify("success", e), g.value += 1, V(); } function A() { - d.value = !1, p.value = null, t.notify("success", s("tasks_projects.time.deleted")), g.value += 1, U(); + d.value = !1, p.value = null, t.notify("success", s("tasks_projects.time.deleted")), g.value += 1, V(); } async function j(e) { if (window.confirm(s("tasks_projects.time.delete_confirm"))) try { - await oa(t.client, e.id), t.notify("success", s("tasks_projects.time.deleted")), g.value += 1, U(); + await je(t.client, e.id), t.notify("success", s("tasks_projects.time.deleted")), g.value += 1, V(); } catch (e) { - t.notify("error", z(e, s("tasks_projects.time.delete_failed"))); + t.notify("error", H(e, s("tasks_projects.time.delete_failed"))); } } function M(e) { return l.value === e ? "border-primary-500 text-primary-500" : "border-transparent text-muted hover:border-line-strong hover:text-heading"; } return (t, n) => (_(), a("section", null, [ - u.value ? (_(), a("nav", Rf, [o("button", { + u.value ? (_(), a("nav", Df, [o("button", { type: "button", class: f(["-mb-px border-b-2 px-1 pb-3 text-sm font-medium", M("MINE")]), onClick: n[0] ||= (e) => l.value = "MINE" @@ -7620,7 +7710,7 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex class: f(["-mb-px border-b-2 px-1 pb-3 text-sm font-medium", M("ALL")]), onClick: n[1] ||= (e) => l.value = "ALL" }, S(C(s)("tasks_projects.time.all_time")), 3)])) : i("", !0), - l.value === "MINE" ? (_(), r(Lf, { + l.value === "MINE" ? (_(), r(Ef, { key: 1, client: e.client, notify: e.notify, @@ -7637,12 +7727,12 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex "project-id", "week-start", "reload-token" - ])) : (_(), r(ff, { + ])) : (_(), r(ef, { key: 2, client: e.client, notify: e.notify, members: e.members, - "member-id": C(xi)(e.filters.user), + "member-id": C(Ki)(e.filters.user), "project-id": b.value, "reload-token": g.value, onEdit: O, @@ -7655,7 +7745,7 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex "project-id", "reload-token" ])), - c(Xo, { + c(Ro, { show: d.value, client: e.client, notify: e.notify, @@ -7673,101 +7763,101 @@ var Id = { class: "flex items-start justify-between gap-2" }, Ld = { class: "tex ]) ])); } -}), Vf = { - viewTask: `${H}:view-task`, - viewOwnTime: `${H}:view-own-time` +}), Af = { + viewTask: `${U}:view-task`, + viewOwnTime: `${U}:view-own-time` }; -function Hf(e) { - e.addMessages(ic), e.registerPage({ +function jf(e) { + e.addMessages(Ks), e.registerPage({ id: "tasks", - module: H, + module: U, path: "", - component: we(e, xl), + component: sn(e, ll), meta: { - ability: Vf.viewTask, + ability: Af.viewTask, title: "tasks_projects.tasks.title" }, children: [ { id: "list", path: "", - component: we(e, sf), + component: sn(e, Yd), meta: { - ability: Vf.viewTask, + ability: Af.viewTask, title: "tasks_projects.tasks.views.list" } }, { id: "board", path: "board", - component: we(e, of), + component: sn(e, Jd), meta: { - ability: Vf.viewTask, + ability: Af.viewTask, title: "tasks_projects.board.title" } }, { id: "week", path: "week", - component: we(e, Bf), + component: sn(e, kf), meta: { - ability: Vf.viewOwnTime, + ability: Af.viewOwnTime, title: "tasks_projects.time.title" } } ] }), e.registerPage({ id: "task", - module: H, + module: U, path: "tasks/:id", - component: we(e, ml), + component: sn(e, nl), meta: { - ability: Vf.viewTask, + ability: Af.viewTask, title: "tasks_projects.tasks.title" } }), e.registerPage({ id: "time", - module: H, + module: U, path: "time", - component: Uf(e), + component: Mf(e), meta: { - ability: Vf.viewOwnTime, + ability: Af.viewOwnTime, title: "tasks_projects.time.title" } }); } -function Uf(e) { +function Mf(e) { return l({ setup: () => (h(() => { - e.router.replace(Se.week); + e.router.replace(W.week); }), () => null) }); } //#endregion //#region resources/js/components/QuickStartOverlay.vue?vue&type=script&setup=true&lang.ts -var Wf = { +var Nf = { key: 0, class: "fixed right-6 bottom-20 z-40 flex flex-col items-end gap-3" -}, Gf = ["aria-label"], Kf = { class: "flex items-center justify-between border-b border-line-default px-4 py-3" }, qf = { class: "text-sm font-semibold text-heading" }, Jf = ["aria-label"], Yf = { +}, Pf = ["aria-label"], Ff = { class: "flex items-center justify-between border-b border-line-default px-4 py-3" }, If = { class: "text-sm font-semibold text-heading" }, Lf = ["aria-label"], Rf = { key: 0, class: "space-y-4 px-4 py-4" -}, Xf = { class: "truncate text-sm font-medium text-heading" }, Zf = { class: "mt-1 text-2xl font-semibold tabular-nums text-primary-500" }, Qf = { +}, zf = { class: "truncate text-sm font-medium text-heading" }, Bf = { class: "mt-1 text-2xl font-semibold tabular-nums text-primary-500" }, Vf = { key: 0, class: "mt-1 text-xs text-muted" -}, $f = { class: "flex items-center gap-2" }, ep = { +}, Hf = { class: "flex items-center gap-2" }, Uf = { key: 1, class: "space-y-3 px-4 py-4" -}, tp = { class: "block" }, np = { class: "sr-only" }, rp = ["placeholder"], ip = { +}, Wf = { class: "block" }, Gf = { class: "sr-only" }, Kf = ["placeholder"], qf = { key: 0, class: "text-xs text-muted" -}, ap = { +}, Jf = { key: 1, class: "max-h-48 space-y-1 overflow-y-auto" -}, op = ["onClick"], sp = { +}, Yf = ["onClick"], Xf = { key: 2, class: "text-xs text-muted" -}, cp = ["placeholder", "aria-label"], lp = { class: "flex items-center justify-between" }, up = ["title", "aria-label"], dp = { +}, Zf = ["placeholder", "aria-label"], Qf = { class: "flex items-center justify-between" }, $f = ["title", "aria-label"], ep = { key: 0, class: "tabular-nums" -}, fp = 300, pp = /* @__PURE__ */ l({ +}, tp = 300, np = /* @__PURE__ */ l({ __name: "QuickStartOverlay", props: { client: { type: [Function, Object] }, @@ -7776,91 +7866,91 @@ var Wf = { }, emits: ["open-week"], setup(l, { emit: u }) { - let d = l, p = u, h = V(), g = y(!1), v = y(""), T = y([]), A = y(!1), j = y(null), M = y(""), N, P = n(() => ({ + let d = l, p = u, h = B(), g = y(!1), v = y(""), T = y([]), A = y(!1), j = y(null), M = y(""), N, P = n(() => ({ notify: d.notify, t: h - })), F = n(() => Ia(G.running?.task_id ?? null)), I = n(() => Ka(G.elapsedSeconds)); + })), F = n(() => Ze(K.running?.task_id ?? null)), I = n(() => Na(K.elapsedSeconds)); E(() => d.enabled, (e) => { - e || R(); + e || z(); }), E(g, (e) => { - e && G.running === null && L(); + e && K.running === null && L(); }), E(v, () => { - clearTimeout(N), N = setTimeout(() => void L(), fp); + clearTimeout(N), N = setTimeout(() => void L(), tp); }), m(() => clearTimeout(N)); async function L() { A.value = !0; try { - let e = await ga(d.client, v.value); - T.value = e, e.forEach(La); + let e = await Ve(d.client, v.value); + T.value = e, e.forEach(Qe); } catch (e) { - T.value = [], d.notify("error", z(e, h("tasks_projects.time.tasks_failed"))); + T.value = [], d.notify("error", H(e, h("tasks_projects.time.tasks_failed"))); } finally { A.value = !1; } } - function ee(e) { - j.value = e, La(e); + function R(e) { + j.value = e, Qe(e); } - function R() { + function z() { g.value = !1, v.value = "", T.value = [], j.value = null, M.value = ""; } - async function te() { + async function ee() { let e = j.value; - e !== null && await G.start(d.client, e.id, M.value.trim() || null, P.value) !== null && (d.notify("success", h("tasks_projects.timer.started", { name: e.name })), R()); + e !== null && await K.start(d.client, e.id, M.value.trim() || null, P.value) !== null && (d.notify("success", h("tasks_projects.timer.started", { name: e.name })), z()); } - async function ne() { - let e = F.value, t = await G.stop(d.client, P.value); + async function te() { + let e = F.value, t = await K.stop(d.client, P.value); t !== null && (d.notify("success", h("tasks_projects.timer.stopped", { name: e, - duration: qa(t.duration_minutes) - })), R()); + duration: Pa(t.duration_minutes) + })), z()); } - async function re() { - window.confirm(h("tasks_projects.timer.discard_confirm")) && await G.discard(d.client, P.value) && (d.notify("success", h("tasks_projects.timer.discarded")), R()); + async function ne() { + window.confirm(h("tasks_projects.timer.discard_confirm")) && await K.discard(d.client, P.value) && (d.notify("success", h("tasks_projects.timer.discarded")), z()); } return (n, u) => { let d = x("BaseIcon"), m = x("BaseButton"); - return _(), r(t, { to: "body" }, [l.enabled ? (_(), a("div", Wf, [g.value ? (_(), a("section", { + return _(), r(t, { to: "body" }, [l.enabled ? (_(), a("div", Nf, [g.value ? (_(), a("section", { key: 0, class: "w-80 max-w-[calc(100vw-3rem)] rounded-xl border border-line-default bg-surface shadow-2xl", "aria-label": C(h)("tasks_projects.timer.panel_title"), - onKeydown: k(R, ["esc"]) - }, [o("header", Kf, [o("h2", qf, S(C(h)("tasks_projects.timer.panel_title")), 1), o("button", { + onKeydown: k(z, ["esc"]) + }, [o("header", Ff, [o("h2", If, S(C(h)("tasks_projects.timer.panel_title")), 1), o("button", { type: "button", class: "rounded p-1 text-subtle hover:bg-hover hover:text-heading", "aria-label": C(h)("tasks_projects.timer.close"), - onClick: R + onClick: z }, [c(d, { name: "XMarkIcon", class: "h-5 w-5" - })], 8, Jf)]), C(G).running === null ? (_(), a("div", ep, [ - o("label", tp, [o("span", np, S(C(h)("tasks_projects.timer.search_tasks")), 1), O(o("input", { + })], 8, Lf)]), C(K).running === null ? (_(), a("div", Uf, [ + o("label", Wf, [o("span", Gf, S(C(h)("tasks_projects.timer.search_tasks")), 1), O(o("input", { "onUpdate:modelValue": u[0] ||= (e) => v.value = e, type: "search", autocomplete: "off", class: "w-full rounded-md border border-line-default bg-surface px-3 py-2 text-sm text-body outline-hidden focus:border-primary-400 focus:ring-1 focus:ring-primary-400", placeholder: C(h)("tasks_projects.timer.search_tasks") - }, null, 8, rp), [[w, v.value]])]), - A.value ? (_(), a("p", ip, S(C(h)("tasks_projects.general.search")), 1)) : T.value.length > 0 ? (_(), a("ul", ap, [(_(!0), a(e, null, b(T.value, (e) => (_(), a("li", { key: e.id }, [o("button", { + }, null, 8, Kf), [[w, v.value]])]), + A.value ? (_(), a("p", qf, S(C(h)("tasks_projects.general.search")), 1)) : T.value.length > 0 ? (_(), a("ul", Jf, [(_(!0), a(e, null, b(T.value, (e) => (_(), a("li", { key: e.id }, [o("button", { type: "button", class: f(["w-full truncate rounded-md px-2 py-2 text-left text-sm hover:bg-hover", j.value?.id === e.id ? "bg-hover-strong font-medium text-heading" : "text-body"]), - onClick: (t) => ee(e) - }, S(e.name), 11, op)]))), 128))])) : (_(), a("p", sp, S(C(h)("tasks_projects.timer.no_tasks")), 1)), + onClick: (t) => R(e) + }, S(e.name), 11, Yf)]))), 128))])) : (_(), a("p", Xf, S(C(h)("tasks_projects.timer.no_tasks")), 1)), O(o("input", { "onUpdate:modelValue": u[1] ||= (e) => M.value = e, type: "text", class: "w-full rounded-md border border-line-default bg-surface px-3 py-2 text-sm text-body outline-hidden focus:border-primary-400 focus:ring-1 focus:ring-primary-400", placeholder: C(h)("tasks_projects.timer.description_placeholder"), "aria-label": C(h)("tasks_projects.time.fields.description") - }, null, 8, cp), [[w, M.value]]), - o("div", lp, [o("button", { + }, null, 8, Zf), [[w, M.value]]), + o("div", Qf, [o("button", { type: "button", class: "text-xs text-primary-500 hover:underline", onClick: u[2] ||= (e) => p("open-week") }, S(C(h)("tasks_projects.timer.open_timesheet")), 1), c(m, { variant: "primary", - disabled: j.value === null || C(G).busy, - onClick: te + disabled: j.value === null || C(K).busy, + onClick: ee }, { left: D((e) => [c(d, { name: "PlayIcon", @@ -7869,14 +7959,14 @@ var Wf = { default: D(() => [s(" " + S(C(h)("tasks_projects.timer.start")), 1)]), _: 1 }, 8, ["disabled"])]) - ])) : (_(), a("div", Yf, [o("div", null, [ - o("p", Xf, S(F.value), 1), - o("p", Zf, S(I.value), 1), - C(G).running.description ? (_(), a("p", Qf, S(C(G).running.description), 1)) : i("", !0) - ]), o("div", $f, [c(m, { + ])) : (_(), a("div", Rf, [o("div", null, [ + o("p", zf, S(F.value), 1), + o("p", Bf, S(I.value), 1), + C(K).running.description ? (_(), a("p", Vf, S(C(K).running.description), 1)) : i("", !0) + ]), o("div", Hf, [c(m, { variant: "primary", - disabled: C(G).busy, - onClick: ne + disabled: C(K).busy, + onClick: te }, { left: D((e) => [c(d, { name: "StopIcon", @@ -7886,31 +7976,31 @@ var Wf = { _: 1 }, 8, ["disabled"]), c(m, { variant: "primary-outline", - disabled: C(G).busy, - onClick: re + disabled: C(K).busy, + onClick: ne }, { default: D(() => [s(S(C(h)("tasks_projects.timer.discard")), 1)]), _: 1 - }, 8, ["disabled"])])]))], 40, Gf)) : i("", !0), o("button", { + }, 8, ["disabled"])])]))], 40, Pf)) : i("", !0), o("button", { type: "button", class: "flex items-center gap-2 rounded-full bg-btn-primary px-4 py-3 text-sm font-medium text-white shadow-lg hover:bg-btn-primary-hover", title: C(h)("tasks_projects.timer.quick_start"), "aria-label": C(h)("tasks_projects.timer.quick_start"), onClick: u[3] ||= (e) => g.value = !g.value }, [c(d, { - name: C(G).running === null ? "ClockIcon" : "StopIcon", + name: C(K).running === null ? "ClockIcon" : "StopIcon", class: "h-5 w-5 text-white" - }, null, 8, ["name"]), C(G).running === null ? i("", !0) : (_(), a("span", dp, S(I.value), 1))], 8, up)])) : i("", !0)]); + }, null, 8, ["name"]), C(K).running === null ? i("", !0) : (_(), a("span", ep, S(I.value), 1))], 8, $f)])) : i("", !0)]); }; } -}), mp = { +}), rp = { key: 0, class: "relative float-left m-0 ml-2" -}, hp = ["title"], gp = ["aria-label", "title"], _p = { class: "font-medium tabular-nums" }, vp = [ +}, ip = ["title"], ap = ["aria-label", "title"], op = { class: "font-medium tabular-nums" }, sp = [ "disabled", "title", "aria-label" -], yp = /* @__PURE__ */ l({ +], cp = /* @__PURE__ */ l({ __name: "TimerChip", props: { client: { type: [Function, Object] }, @@ -7918,20 +8008,20 @@ var Wf = { }, emits: ["open"], setup(e, { emit: t }) { - let r = e, s = t, l = V(), u = n(() => Ia(G.running?.task_id ?? null)), d = n(() => Ka(G.elapsedSeconds)); + let r = e, s = t, l = B(), u = n(() => Ze(K.running?.task_id ?? null)), d = n(() => Na(K.elapsedSeconds)); async function f() { - let e = u.value, t = await G.stop(r.client, { + let e = u.value, t = await K.stop(r.client, { notify: r.notify, t: l }); t !== null && r.notify("success", l("tasks_projects.timer.stopped", { name: e, - duration: qa(t.duration_minutes) + duration: Pa(t.duration_minutes) })); } return (e, t) => { let n = x("BaseIcon"); - return C(G).running === null ? i("", !0) : (_(), a("li", mp, [o("div", { + return C(K).running === null ? i("", !0) : (_(), a("li", rp, [o("div", { class: "flex h-8 items-center gap-2 rounded-lg bg-white/20 px-2 text-sm text-white md:h-9 md:px-3", title: C(l)("tasks_projects.timer.running") }, [ @@ -7942,23 +8032,23 @@ var Wf = { "aria-label": C(l)("tasks_projects.timer.open_task"), title: C(l)("tasks_projects.timer.open_task"), onClick: t[0] ||= (e) => s("open") - }, S(u.value), 9, gp), - o("span", _p, S(d.value), 1), + }, S(u.value), 9, ap), + o("span", op, S(d.value), 1), o("button", { type: "button", class: "rounded p-1 hover:bg-white/20 disabled:opacity-50", - disabled: C(G).busy, + disabled: C(K).busy, title: C(l)("tasks_projects.timer.stop"), "aria-label": C(l)("tasks_projects.timer.stop"), onClick: f }, [c(n, { name: "StopIcon", class: "h-4 w-4 text-white" - })], 8, vp) - ], 8, hp)])); + })], 8, sp) + ], 8, ip)])); }; } -}), bp = { en: { tasks_projects: { +}), lp = { en: { tasks_projects: { time: { title: "Time", my_time: "My time", @@ -8111,47 +8201,47 @@ var Wf = { reorder_failed: "Unable to save the new order.", forbidden: "Your role does not allow managing the board columns." } -} } }, xp = { +} } }, up = { key: 0, class: "text-sm text-muted" -}, Sp = { key: 1 }, Cp = { +}, dp = { key: 1 }, fp = { key: 0, class: "flex items-center gap-2 text-sm text-muted" -}, wp = { +}, pp = { key: 1, class: "text-sm text-muted" -}, Tp = { +}, mp = { key: 2, class: "divide-y divide-line-light" -}, Ep = { +}, hp = { key: 0, class: "space-y-3" -}, Dp = { class: "flex flex-wrap items-center gap-2" }, Op = ["aria-label", "onClick"], kp = { class: "flex flex-wrap items-center gap-6" }, Ap = { class: "flex items-center gap-2 text-sm text-body" }, jp = { class: "flex items-center gap-2 text-sm text-body" }, Mp = { class: "flex gap-3" }, Np = { +}, gp = { class: "flex flex-wrap items-center gap-2" }, _p = ["aria-label", "onClick"], vp = { class: "flex flex-wrap items-center gap-6" }, yp = { class: "flex items-center gap-2 text-sm text-body" }, bp = { class: "flex items-center gap-2 text-sm text-body" }, xp = { class: "flex gap-3" }, Sp = { key: 1, class: "flex items-center gap-3" -}, Pp = { class: "min-w-0 flex-1 truncate text-sm font-medium text-heading" }, Fp = { class: "flex items-center gap-1" }, Ip = [ +}, Cp = { class: "min-w-0 flex-1 truncate text-sm font-medium text-heading" }, wp = { class: "flex items-center gap-1" }, Tp = [ "disabled", "title", "aria-label", "onClick" -], Lp = [ +], Ep = [ "disabled", "title", "aria-label", "onClick" -], Rp = [ +], Dp = [ "title", "aria-label", "onClick" -], zp = [ +], Op = [ "disabled", "title", "aria-label", "onClick" -], Bp = { +], kp = { key: 3, class: "mt-4 space-y-3 rounded-lg border border-line-default p-3" -}, Vp = { class: "flex flex-wrap items-center gap-2" }, Hp = ["aria-label", "onClick"], Up = { class: "flex flex-wrap items-center gap-6" }, Wp = { class: "flex items-center gap-2 text-sm text-body" }, Gp = { class: "flex items-center gap-2 text-sm text-body" }, Kp = { class: "flex gap-3" }, qp = /* @__PURE__ */ l({ +}, Ap = { class: "flex flex-wrap items-center gap-2" }, jp = ["aria-label", "onClick"], Mp = { class: "flex flex-wrap items-center gap-6" }, Np = { class: "flex items-center gap-2 text-sm text-body" }, Pp = { class: "flex items-center gap-2 text-sm text-body" }, Fp = { class: "flex gap-3" }, Ip = /* @__PURE__ */ l({ __name: "TaskStatusEditor", props: { client: { type: [Function, Object] }, @@ -8167,7 +8257,7 @@ var Wf = { "#a855f7", "#0891b2", "#64748b" - ], d = V(), m = y([]), g = y(!0), w = y(!1), T = y(!1), E = y(null), O = y(!1), k = v({ + ], d = B(), m = y([]), g = y(!0), w = y(!1), T = y(!1), E = y(null), O = y(!1), k = v({ name: "", colour: "", is_default: !1, @@ -8177,9 +8267,9 @@ var Wf = { async function j() { g.value = !0; try { - m.value = await da(l.client), w.value = !1; + m.value = await Ie(l.client), w.value = !1; } catch (e) { - m.value = [], w.value = de(e), w.value || l.notify("error", z(e, d("tasks_projects.settings.load_failed"))); + m.value = [], w.value = vt(e), w.value || l.notify("error", H(e, d("tasks_projects.settings.load_failed"))); } finally { g.value = !1; } @@ -8210,9 +8300,9 @@ var Wf = { let e = E.value, t = k.name.trim(); T.value = !0; try { - e === null ? (await fa(l.client, F()), l.notify("success", d("tasks_projects.settings.status_created", { name: t }))) : (await pa(l.client, e, F()), l.notify("success", d("tasks_projects.settings.status_updated", { name: t }))), P(), await j(); + e === null ? (await Le(l.client, F()), l.notify("success", d("tasks_projects.settings.status_created", { name: t }))) : (await Re(l.client, e, F()), l.notify("success", d("tasks_projects.settings.status_updated", { name: t }))), P(), await j(); } catch (e) { - l.notify("error", z(e, d("tasks_projects.settings.save_failed"))); + l.notify("error", H(e, d("tasks_projects.settings.save_failed"))); } finally { T.value = !1; } @@ -8221,33 +8311,33 @@ var Wf = { if (!T.value && window.confirm(d("tasks_projects.settings.status_delete_confirm", { name: e.name }))) { T.value = !0; try { - await ma(l.client, e.id), l.notify("success", d("tasks_projects.settings.status_deleted", { name: e.name })), P(), await j(); + await ze(l.client, e.id), l.notify("success", d("tasks_projects.settings.status_deleted", { name: e.name })), P(), await j(); } catch (e) { - l.notify("error", z(e, d("tasks_projects.settings.delete_failed"))); + l.notify("error", H(e, d("tasks_projects.settings.delete_failed"))); } finally { T.value = !1; } } } - async function ee(e, t) { + async function R(e, t) { let n = e + t; if (T.value || n < 0 || n >= m.value.length) return; let r = [...m.value]; r.splice(n, 0, ...r.splice(e, 1)), m.value = r, T.value = !0; try { - m.value = await ha(l.client, r.map((e) => e.id)), l.notify("success", d("tasks_projects.settings.status_reordered")); + m.value = await Be(l.client, r.map((e) => e.id)), l.notify("success", d("tasks_projects.settings.status_reordered")); } catch (e) { - l.notify("error", z(e, d("tasks_projects.settings.reorder_failed"))), await j(); + l.notify("error", H(e, d("tasks_projects.settings.reorder_failed"))), await j(); } finally { T.value = !1; } } return (t, n) => { - let l = x("BaseSpinner"), h = x("BaseInput"), v = x("BaseInputGroup"), y = x("BaseSwitch"), j = x("BaseButton"), F = x("BaseBadge"), R = x("BaseIcon"); - return _(), a("div", null, [w.value ? (_(), a("p", xp, S(C(d)("tasks_projects.settings.forbidden")), 1)) : (_(), a("div", Sp, [g.value ? (_(), a("div", Cp, [c(l, { class: "h-4 w-4 text-primary-500" })])) : A.value ? (_(), a("p", wp, S(C(d)("tasks_projects.settings.no_statuses")), 1)) : (_(), a("ul", Tp, [(_(!0), a(e, null, b(m.value, (t, l) => (_(), a("li", { + let l = x("BaseSpinner"), h = x("BaseInput"), v = x("BaseInputGroup"), y = x("BaseSwitch"), j = x("BaseButton"), F = x("BaseBadge"), z = x("BaseIcon"); + return _(), a("div", null, [w.value ? (_(), a("p", up, S(C(d)("tasks_projects.settings.forbidden")), 1)) : (_(), a("div", dp, [g.value ? (_(), a("div", fp, [c(l, { class: "h-4 w-4 text-primary-500" })])) : A.value ? (_(), a("p", pp, S(C(d)("tasks_projects.settings.no_statuses")), 1)) : (_(), a("ul", mp, [(_(!0), a(e, null, b(m.value, (t, l) => (_(), a("li", { key: t.id, class: "py-3" - }, [E.value === t.id ? (_(), a("div", Ep, [ + }, [E.value === t.id ? (_(), a("div", hp, [ c(v, { label: C(d)("tasks_projects.settings.status_name"), required: "" @@ -8261,30 +8351,30 @@ var Wf = { _: 1 }, 8, ["label"]), c(v, { label: C(d)("tasks_projects.settings.colour") }, { - default: D(() => [o("div", Dp, [(_(), a(e, null, b(u, (e) => o("button", { + default: D(() => [o("div", gp, [(_(), a(e, null, b(u, (e) => o("button", { key: e, type: "button", class: f(["h-7 w-7 rounded-full border-2 transition", k.colour === e ? "border-heading" : "border-line-default"]), style: p({ backgroundColor: e }), "aria-label": e, onClick: (t) => k.colour = e - }, null, 14, Op)), 64)), o("button", { + }, null, 14, _p)), 64)), o("button", { type: "button", class: "rounded-md border border-line-default px-2 py-1 text-xs text-muted hover:bg-hover", onClick: n[1] ||= (e) => k.colour = "" }, S(C(d)("tasks_projects.settings.colour_none")), 1)])]), _: 1 }, 8, ["label"]), - o("div", kp, [o("label", Ap, [c(y, { + o("div", vp, [o("label", yp, [c(y, { modelValue: k.is_default, "onUpdate:modelValue": n[2] ||= (e) => k.is_default = e, class: "flex" - }, null, 8, ["modelValue"]), s(" " + S(C(d)("tasks_projects.settings.is_default")), 1)]), o("label", jp, [c(y, { + }, null, 8, ["modelValue"]), s(" " + S(C(d)("tasks_projects.settings.is_default")), 1)]), o("label", bp, [c(y, { modelValue: k.is_closed, "onUpdate:modelValue": n[3] ||= (e) => k.is_closed = e, class: "flex" }, null, 8, ["modelValue"]), s(" " + S(C(d)("tasks_projects.settings.is_closed")), 1)])]), - o("div", Mp, [c(j, { + o("div", xp, [c(j, { variant: "primary", size: "sm", disabled: T.value, @@ -8300,12 +8390,12 @@ var Wf = { default: D(() => [s(S(C(d)("tasks_projects.general.cancel")), 1)]), _: 1 })]) - ])) : (_(), a("div", Np, [ + ])) : (_(), a("div", Sp, [ o("span", { class: f(["inline-block h-3 w-3 shrink-0 rounded-full", t.colour ? "" : "bg-line-default"]), style: p(t.colour ? { backgroundColor: t.colour } : void 0) }, null, 6), - o("span", Pp, S(t.name), 1), + o("span", Cp, S(t.name), 1), t.is_default ? (_(), r(F, { key: 0, class: "rounded-full bg-primary-50! text-primary-500!" @@ -8320,39 +8410,39 @@ var Wf = { default: D(() => [s(S(C(d)("tasks_projects.settings.is_closed")), 1)]), _: 1 })) : i("", !0), - o("div", Fp, [ + o("div", wp, [ o("button", { type: "button", class: "rounded p-1 text-subtle hover:bg-hover hover:text-heading disabled:opacity-40", disabled: T.value || l === 0, title: C(d)("tasks_projects.settings.move_up"), "aria-label": C(d)("tasks_projects.settings.move_up"), - onClick: (e) => ee(l, -1) - }, [c(R, { + onClick: (e) => R(l, -1) + }, [c(z, { name: "ChevronUpIcon", class: "h-4 w-4" - })], 8, Ip), + })], 8, Tp), o("button", { type: "button", class: "rounded p-1 text-subtle hover:bg-hover hover:text-heading disabled:opacity-40", disabled: T.value || l === m.value.length - 1, title: C(d)("tasks_projects.settings.move_down"), "aria-label": C(d)("tasks_projects.settings.move_down"), - onClick: (e) => ee(l, 1) - }, [c(R, { + onClick: (e) => R(l, 1) + }, [c(z, { name: "ChevronDownIcon", class: "h-4 w-4" - })], 8, Lp), + })], 8, Ep), o("button", { type: "button", class: "rounded p-1 text-subtle hover:bg-hover hover:text-heading", title: C(d)("tasks_projects.general.edit"), "aria-label": C(d)("tasks_projects.general.edit"), onClick: (e) => M(t) - }, [c(R, { + }, [c(z, { name: "PencilIcon", class: "h-4 w-4" - })], 8, Rp), + })], 8, Dp), o("button", { type: "button", class: "rounded p-1 text-subtle hover:bg-hover hover:text-alert-error-text", @@ -8360,12 +8450,12 @@ var Wf = { title: C(d)("tasks_projects.general.delete"), "aria-label": C(d)("tasks_projects.general.delete"), onClick: (e) => L(t) - }, [c(R, { + }, [c(z, { name: "TrashIcon", class: "h-4 w-4" - })], 8, zp) + })], 8, Op) ]) - ]))]))), 128))])), O.value ? (_(), a("div", Bp, [ + ]))]))), 128))])), O.value ? (_(), a("div", kp, [ c(v, { label: C(d)("tasks_projects.settings.status_name"), required: "" @@ -8379,26 +8469,26 @@ var Wf = { _: 1 }, 8, ["label"]), c(v, { label: C(d)("tasks_projects.settings.colour") }, { - default: D(() => [o("div", Vp, [(_(), a(e, null, b(u, (e) => o("button", { + default: D(() => [o("div", Ap, [(_(), a(e, null, b(u, (e) => o("button", { key: e, type: "button", class: f(["h-7 w-7 rounded-full border-2 transition", k.colour === e ? "border-heading" : "border-line-default"]), style: p({ backgroundColor: e }), "aria-label": e, onClick: (t) => k.colour = e - }, null, 14, Hp)), 64))])]), + }, null, 14, jp)), 64))])]), _: 1 }, 8, ["label"]), - o("div", Up, [o("label", Wp, [c(y, { + o("div", Mp, [o("label", Np, [c(y, { modelValue: k.is_default, "onUpdate:modelValue": n[5] ||= (e) => k.is_default = e, class: "flex" - }, null, 8, ["modelValue"]), s(" " + S(C(d)("tasks_projects.settings.is_default")), 1)]), o("label", Gp, [c(y, { + }, null, 8, ["modelValue"]), s(" " + S(C(d)("tasks_projects.settings.is_default")), 1)]), o("label", Pp, [c(y, { modelValue: k.is_closed, "onUpdate:modelValue": n[6] ||= (e) => k.is_closed = e, class: "flex" }, null, 8, ["modelValue"]), s(" " + S(C(d)("tasks_projects.settings.is_closed")), 1)])]), - o("div", Kp, [c(j, { + o("div", Fp, [c(j, { variant: "primary", size: "sm", disabled: T.value, @@ -8421,7 +8511,7 @@ var Wf = { class: "mt-4", onClick: N }, { - left: D((e) => [c(R, { + left: D((e) => [c(z, { name: "PlusIcon", class: f(e.class) }, null, 8, ["class"])]), @@ -8430,7 +8520,7 @@ var Wf = { }))]))]); }; } -}), Jp = { class: "space-y-6" }, Yp = { class: "divide-y divide-line-light" }, Xp = { class: "text-sm text-muted" }, Zp = { class: "text-sm font-medium text-heading" }, Qp = { class: "divide-y divide-line-light" }, $p = { class: "text-sm text-muted" }, em = { class: "text-sm font-medium text-heading" }, tm = /* @__PURE__ */ l({ +}), Lp = { class: "space-y-6" }, Rp = { class: "divide-y divide-line-light" }, zp = { class: "text-sm text-muted" }, Bp = { class: "text-sm font-medium text-heading" }, Vp = { class: "divide-y divide-line-light" }, Hp = { class: "text-sm text-muted" }, Up = { class: "text-sm font-medium text-heading" }, Wp = /* @__PURE__ */ l({ __name: "TimeSettingsPage", props: { client: { type: [Function, Object] }, @@ -8438,7 +8528,7 @@ var Wf = { router: {} }, setup(t) { - let r = V(), i = n(() => xa.settings); + let r = B(), i = n(() => xa.settings); function l(e) { return r(e ? "tasks_projects.settings.on" : "tasks_projects.settings.off"); } @@ -8482,12 +8572,12 @@ var Wf = { }))); return (n, i) => { let l = x("BaseIcon"), p = x("BaseButton"), m = x("router-link"), h = x("BaseSettingCard"); - return _(), a("div", Jp, [ + return _(), a("div", Lp, [ c(h, { title: C(r)("tasks_projects.settings.general_title"), description: C(r)("tasks_projects.settings.general_description") }, { - action: D(() => [c(m, { to: C(Se).settings }, { + action: D(() => [c(m, { to: C(W).settings }, { default: D(() => [c(p, { variant: "primary-outline", size: "sm" @@ -8507,27 +8597,27 @@ var Wf = { title: C(r)("tasks_projects.settings.behaviour_title"), description: C(r)("tasks_projects.settings.behaviour_description") }, { - default: D(() => [o("dl", Yp, [(_(!0), a(e, null, b(u.value, (e) => (_(), a("div", { + default: D(() => [o("dl", Rp, [(_(!0), a(e, null, b(u.value, (e) => (_(), a("div", { key: e.key, class: "flex justify-between gap-4 py-2.5" - }, [o("dt", Xp, S(e.label), 1), o("dd", Zp, S(e.value), 1)]))), 128))])]), + }, [o("dt", zp, S(e.label), 1), o("dd", Bp, S(e.value), 1)]))), 128))])]), _: 1 }, 8, ["title", "description"]), c(h, { title: C(r)("tasks_projects.settings.invoice_title"), description: C(r)("tasks_projects.settings.invoice_description") }, { - default: D(() => [o("dl", Qp, [(_(!0), a(e, null, b(d.value, (e) => (_(), a("div", { + default: D(() => [o("dl", Vp, [(_(!0), a(e, null, b(d.value, (e) => (_(), a("div", { key: e.key, class: "flex justify-between gap-4 py-2.5" - }, [o("dt", $p, S(e.label), 1), o("dd", em, S(e.value), 1)]))), 128))])]), + }, [o("dt", Hp, S(e.label), 1), o("dd", Up, S(e.value), 1)]))), 128))])]), _: 1 }, 8, ["title", "description"]), c(h, { title: C(r)("tasks_projects.settings.statuses_title"), description: C(r)("tasks_projects.settings.statuses_description") }, { - default: D(() => [c(qp, { + default: D(() => [c(Ip, { client: t.client, notify: t.notify }, null, 8, ["client", "notify"])]), @@ -8539,28 +8629,28 @@ var Wf = { }); //#endregion //#region resources/js/registrations/time.ts -function nm(e) { - e.addMessages(bp); +function Gp(e) { + e.addMessages(lp); let t = (t, n) => { e.notify(t, n); }, n = () => { - e.router.push(Se.week); + e.router.push(W.week); }, r = () => { - let t = G.runningTaskId; - e.router.push(t === null ? Se.week : Se.task(t)); + let t = K.runningTaskId; + e.router.push(t === null ? W.week : W.task(t)); }; e.registerHeaderAction({ - id: `${H}.timer-chip`, + id: `${U}.timer-chip`, priority: 30, - visible: () => G.running !== null, - component: l({ setup: () => () => d(yp, { + visible: () => K.running !== null, + component: l({ setup: () => () => d(cp, { client: e.client, notify: t, onOpen: r }) }) }), e.registerCompanyLayoutOverlay({ - id: `${H}.quick-start`, - component: l({ setup: () => () => d(pp, { + id: `${U}.quick-start`, + component: l({ setup: () => () => d(np, { key: xa.companySession, client: e.client, notify: t, @@ -8568,33 +8658,33 @@ function nm(e) { onOpenWeek: n }) }) }), e.registerCompanySettingsPage({ - id: `${H}.settings`, + id: `${U}.settings`, title: "tasks_projects.settings.title", icon: "ClockIcon", - path: H, + path: U, priority: 70, - component: we(e, tm) + component: sn(e, Wp) }), e.on("bootstrap:completed", ({ adminMode: t }) => { - rm(e, t); + Kp(e, t); }), e.on("company:changing", () => { - im(); + qp(); }), e.on("company:changed", ({ companyId: t }) => { - rm(e, t === null); + Kp(e, t === null); }); } -async function rm(e, t) { +async function Kp(e, t) { if (wa(t), t) { - im(); + qp(); return; } - await Sa(e.client), await G.refresh(e.client); + await Sa(e.client), await K.refresh(e.client); } -function im() { - G.reset(), Ha(), Ca(); +function qp() { + K.reset(), rt(), Ca(); } //#endregion //#region resources/js/init.ts window.InvoiceShelf.booting((e, t, n) => { - n.addMessages(j), Hf(n), cs(n), nm(n), un(n), rc(n); + n.addMessages(j), jf(n), Xo(n), Gp(n), nr(n), Gs(n); }); //#endregion diff --git a/dist/style.css b/dist/style.css index 6a907af..2639ee3 100644 --- a/dist/style.css +++ b/dist/style.css @@ -1,3 +1,3 @@ /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */ -@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer utilities{.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.fixed{position:fixed}.relative{position:relative}.right-6{right:calc(var(--spacing,.25rem) * 6)}.bottom-20{bottom:calc(var(--spacing,.25rem) * 20)}.z-40{z-index:40}.float-left{float:left}.m-0{margin:0}.mx-auto{margin-inline:auto}.mt-1{margin-top:var(--spacing,.25rem)}.mt-2{margin-top:calc(var(--spacing,.25rem) * 2)}.mt-3{margin-top:calc(var(--spacing,.25rem) * 3)}.mt-4{margin-top:calc(var(--spacing,.25rem) * 4)}.mt-5{margin-top:calc(var(--spacing,.25rem) * 5)}.mt-6{margin-top:calc(var(--spacing,.25rem) * 6)}.mr-2{margin-right:calc(var(--spacing,.25rem) * 2)}.mr-3{margin-right:calc(var(--spacing,.25rem) * 3)}.-mb-px{margin-bottom:-1px}.mb-1{margin-bottom:var(--spacing,.25rem)}.mb-3{margin-bottom:calc(var(--spacing,.25rem) * 3)}.mb-4{margin-bottom:calc(var(--spacing,.25rem) * 4)}.ml-1{margin-left:var(--spacing,.25rem)}.ml-2{margin-left:calc(var(--spacing,.25rem) * 2)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.h-1\.5{height:calc(var(--spacing,.25rem) * 1.5)}.h-2{height:calc(var(--spacing,.25rem) * 2)}.h-2\.5{height:calc(var(--spacing,.25rem) * 2.5)}.h-3{height:calc(var(--spacing,.25rem) * 3)}.h-3\.5{height:calc(var(--spacing,.25rem) * 3.5)}.h-4{height:calc(var(--spacing,.25rem) * 4)}.h-5{height:calc(var(--spacing,.25rem) * 5)}.h-6{height:calc(var(--spacing,.25rem) * 6)}.h-7{height:calc(var(--spacing,.25rem) * 7)}.h-8{height:calc(var(--spacing,.25rem) * 8)}.h-12{height:calc(var(--spacing,.25rem) * 12)}.h-16{height:calc(var(--spacing,.25rem) * 16)}.max-h-48{max-height:calc(var(--spacing,.25rem) * 48)}.min-h-20{min-height:calc(var(--spacing,.25rem) * 20)}.min-h-40{min-height:calc(var(--spacing,.25rem) * 40)}.w-1\.5{width:calc(var(--spacing,.25rem) * 1.5)}.w-2{width:calc(var(--spacing,.25rem) * 2)}.w-2\.5{width:calc(var(--spacing,.25rem) * 2.5)}.w-3{width:calc(var(--spacing,.25rem) * 3)}.w-3\.5{width:calc(var(--spacing,.25rem) * 3.5)}.w-4{width:calc(var(--spacing,.25rem) * 4)}.w-5{width:calc(var(--spacing,.25rem) * 5)}.w-6{width:calc(var(--spacing,.25rem) * 6)}.w-7{width:calc(var(--spacing,.25rem) * 7)}.w-8{width:calc(var(--spacing,.25rem) * 8)}.w-10{width:calc(var(--spacing,.25rem) * 10)}.w-12{width:calc(var(--spacing,.25rem) * 12)}.w-16{width:calc(var(--spacing,.25rem) * 16)}.w-72{width:calc(var(--spacing,.25rem) * 72)}.w-80{width:calc(var(--spacing,.25rem) * 80)}.w-full{width:100%}.max-w-32{max-width:calc(var(--spacing,.25rem) * 32)}.max-w-64{max-width:calc(var(--spacing,.25rem) * 64)}.max-w-\[calc\(100vw-3rem\)\]{max-width:calc(100vw - 3rem)}.min-w-0{min-width:0}.min-w-44{min-width:calc(var(--spacing,.25rem) * 44)}.min-w-48{min-width:calc(var(--spacing,.25rem) * 48)}.min-w-full{min-width:100%}.flex-1{flex:1}.shrink-0{flex-shrink:0}.table-auto{table-layout:auto}.animate-pulse{animation:var(--animate-pulse,pulse 2s cubic-bezier(.4, 0, .6, 1) infinite)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing,.25rem)}.gap-1\.5{gap:calc(var(--spacing,.25rem) * 1.5)}.gap-2{gap:calc(var(--spacing,.25rem) * 2)}.gap-3{gap:calc(var(--spacing,.25rem) * 3)}.gap-4{gap:calc(var(--spacing,.25rem) * 4)}.gap-6{gap:calc(var(--spacing,.25rem) * 6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(var(--spacing,.25rem) * var(--tw-space-y-reverse));margin-block-end:calc(var(--spacing,.25rem) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing,.25rem) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing,.25rem) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing,.25rem) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing,.25rem) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing,.25rem) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing,.25rem) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing,.25rem) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing,.25rem) * 5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing,.25rem) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing,.25rem) * 6) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-6{column-gap:calc(var(--spacing,.25rem) * 6)}:where(.space-x-3>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing,.25rem) * 3) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing,.25rem) * 3) * calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-5>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing,.25rem) * 5) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing,.25rem) * 5) * calc(1 - var(--tw-space-x-reverse)))}.gap-y-3{row-gap:calc(var(--spacing,.25rem) * 3)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-line-default>:not(:last-child)){border-color:var(--color-line-default)}:where(.divide-line-light>:not(:last-child)){border-color:var(--color-line-light)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg,.5rem)}.rounded-md{border-radius:var(--radius-md,.375rem)}.rounded-sm{border-radius:var(--radius-sm,.25rem)}.rounded-xl{border-radius:var(--radius-xl,.75rem)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-heading{border-color:var(--color-heading)}.border-line-default{border-color:var(--color-line-default)}.border-line-light{border-color:var(--color-line-light)}.border-line-strong{border-color:var(--color-line-strong)}.border-primary-200{border-color:var(--color-primary-200)}.border-primary-400{border-color:var(--color-primary-400)}.border-primary-500{border-color:var(--color-primary-500)}.border-status-red{border-color:var(--color-status-red)}.border-status-yellow{border-color:var(--color-status-yellow)}.border-transparent{border-color:#0000}.bg-alert-error-bg{background-color:var(--color-alert-error-bg)}.bg-alert-success-bg\!{background-color:var(--color-alert-success-bg)!important}.bg-alert-warning-bg{background-color:var(--color-alert-warning-bg)}.bg-alert-warning-bg\!{background-color:var(--color-alert-warning-bg)!important}.bg-btn-primary{background-color:var(--color-btn-primary)}.bg-hover-strong{background-color:var(--color-hover-strong)}.bg-line-default{background-color:var(--color-line-default)}.bg-line-strong{background-color:var(--color-line-strong)}.bg-primary-50{background-color:var(--color-primary-50)}.bg-primary-50\!{background-color:var(--color-primary-50)!important}.bg-primary-500{background-color:var(--color-primary-500)}.bg-status-green{background-color:var(--color-status-green)}.bg-status-red{background-color:var(--color-status-red)}.bg-surface{background-color:var(--color-surface)}.bg-surface-secondary{background-color:var(--color-surface-secondary)}.bg-surface-tertiary{background-color:var(--color-surface-tertiary)}.bg-surface-tertiary\!{background-color:var(--color-surface-tertiary)!important}.bg-white{background-color:var(--color-white,#fff)}.bg-white\/20{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.bg-white\/20{background-color:color-mix(in oklab, var(--color-white,#fff) 20%, transparent)}}.p-1{padding:var(--spacing,.25rem)}.p-1\.5{padding:calc(var(--spacing,.25rem) * 1.5)}.p-2{padding:calc(var(--spacing,.25rem) * 2)}.p-3{padding:calc(var(--spacing,.25rem) * 3)}.p-5{padding:calc(var(--spacing,.25rem) * 5)}.p-6{padding:calc(var(--spacing,.25rem) * 6)}.px-1{padding-inline:var(--spacing,.25rem)}.px-1\.5{padding-inline:calc(var(--spacing,.25rem) * 1.5)}.px-2{padding-inline:calc(var(--spacing,.25rem) * 2)}.px-3{padding-inline:calc(var(--spacing,.25rem) * 3)}.px-4{padding-inline:calc(var(--spacing,.25rem) * 4)}.px-5{padding-inline:calc(var(--spacing,.25rem) * 5)}.px-6{padding-inline:calc(var(--spacing,.25rem) * 6)}.py-0\.5{padding-block:calc(var(--spacing,.25rem) * .5)}.py-1{padding-block:var(--spacing,.25rem)}.py-1\.5{padding-block:calc(var(--spacing,.25rem) * 1.5)}.py-2{padding-block:calc(var(--spacing,.25rem) * 2)}.py-2\.5{padding-block:calc(var(--spacing,.25rem) * 2.5)}.py-3{padding-block:calc(var(--spacing,.25rem) * 3)}.py-4{padding-block:calc(var(--spacing,.25rem) * 4)}.py-6{padding-block:calc(var(--spacing,.25rem) * 6)}.py-8{padding-block:calc(var(--spacing,.25rem) * 8)}.py-10{padding-block:calc(var(--spacing,.25rem) * 10)}.py-16{padding-block:calc(var(--spacing,.25rem) * 16)}.pt-2{padding-top:calc(var(--spacing,.25rem) * 2)}.pt-3{padding-top:calc(var(--spacing,.25rem) * 3)}.pb-2{padding-bottom:calc(var(--spacing,.25rem) * 2)}.pb-3{padding-bottom:calc(var(--spacing,.25rem) * 3)}.pb-4{padding-bottom:calc(var(--spacing,.25rem) * 4)}.pl-4{padding-left:calc(var(--spacing,.25rem) * 4)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.text-2xl{font-size:var(--text-2xl,1.5rem);line-height:var(--tw-leading,var(--text-2xl--line-height,calc(2 / 1.5)))}.text-base{font-size:var(--text-base,1rem);line-height:var(--tw-leading,var(--text-base--line-height,calc(1.5 / 1)))}.text-lg{font-size:var(--text-lg,1.125rem);line-height:var(--tw-leading,var(--text-lg--line-height,calc(1.75 / 1.125)))}.text-sm{font-size:var(--text-sm,.875rem);line-height:var(--tw-leading,var(--text-sm--line-height,calc(1.25 / .875)))}.text-xl{font-size:var(--text-xl,1.25rem);line-height:var(--tw-leading,var(--text-xl--line-height,calc(1.75 / 1.25)))}.text-xs{font-size:var(--text-xs,.75rem);line-height:var(--tw-leading,var(--text-xs--line-height,calc(1 / .75)))}.text-\[11px\]{font-size:11px}.leading-5{--tw-leading:calc(var(--spacing,.25rem) * 5);line-height:calc(var(--spacing,.25rem) * 5)}.font-medium{--tw-font-weight:var(--font-weight-medium,500);font-weight:var(--font-weight-medium,500)}.font-normal{--tw-font-weight:var(--font-weight-normal,400);font-weight:var(--font-weight-normal,400)}.font-semibold{--tw-font-weight:var(--font-weight-semibold,600);font-weight:var(--font-weight-semibold,600)}.tracking-wide{--tw-tracking:var(--tracking-wide,.025em);letter-spacing:var(--tracking-wide,.025em)}.tracking-wider{--tw-tracking:var(--tracking-wider,.05em);letter-spacing:var(--tracking-wider,.05em)}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.text-alert-error-text{color:var(--color-alert-error-text)}.text-alert-success-text\!{color:var(--color-alert-success-text)!important}.text-alert-warning-text{color:var(--color-alert-warning-text)}.text-alert-warning-text\!{color:var(--color-alert-warning-text)!important}.text-body{color:var(--color-body)}.text-heading{color:var(--color-heading)}.text-muted{color:var(--color-muted)}.text-muted\!{color:var(--color-muted)!important}.text-primary-500{color:var(--color-primary-500)}.text-primary-500\!{color:var(--color-primary-500)!important}.text-primary-600{color:var(--color-primary-600)}.text-primary-700{color:var(--color-primary-700)}.text-status-green{color:var(--color-status-green)}.text-status-red{color:var(--color-status-red)}.text-subtle{color:var(--color-subtle)}.text-white{color:var(--color-white,#fff)}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.opacity-40{opacity:.4}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline-hidden{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.outline-hidden{outline-offset:2px;outline:2px solid #0000}}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function,cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration,var(--default-transition-duration,.15s))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function,cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration,var(--default-transition-duration,.15s))}@media (hover:hover){.group-hover\:text-muted:is(:where(.group):hover *){color:var(--color-muted)}}.last\:border-r-0:last-child{border-right-style:var(--tw-border-style);border-right-width:0}@media (hover:hover){.hover\:border-line-strong:hover{border-color:var(--color-line-strong)}.hover\:border-primary-500:hover{border-color:var(--color-primary-500)}.hover\:bg-btn-primary-hover:hover{background-color:var(--color-btn-primary-hover)}.hover\:bg-hover:hover{background-color:var(--color-hover)}.hover\:bg-white\/20:hover{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/20:hover{background-color:color-mix(in oklab, var(--color-white,#fff) 20%, transparent)}}.hover\:text-alert-error-text:hover{color:var(--color-alert-error-text)}.hover\:text-body:hover{color:var(--color-body)}.hover\:text-heading:hover{color:var(--color-heading)}.hover\:text-primary-500:hover{color:var(--color-primary-500)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:border-primary-400:focus{border-color:var(--color-primary-400)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-primary-400:focus{--tw-ring-color:var(--color-primary-400)}.focus\:outline-hidden:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.focus\:outline-hidden:focus{outline-offset:2px;outline:2px solid #0000}}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media not all and (width>=40rem){.max-sm\:hidden{display:none}}@media (width>=40rem){.sm\:w-48{width:calc(var(--spacing,.25rem) * 48)}.sm\:w-56{width:calc(var(--spacing,.25rem) * 56)}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (width>=48rem){.md\:h-9{height:calc(var(--spacing,.25rem) * 9)}.md\:px-3{padding-inline:calc(var(--spacing,.25rem) * 3)}}@media (width>=64rem){.lg\:mb-1{margin-bottom:var(--spacing,.25rem)}.lg\:block{display:block}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:flex-row{flex-direction:row}.lg\:items-end{align-items:flex-end}}@media (width>=80rem){.xl\:grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}} +@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer utilities{.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.fixed{position:fixed}.relative{position:relative}.right-6{right:calc(var(--spacing,.25rem) * 6)}.bottom-20{bottom:calc(var(--spacing,.25rem) * 20)}.z-40{z-index:40}.float-left{float:left}.m-0{margin:0}.mt-0\.5{margin-top:calc(var(--spacing,.25rem) * .5)}.mt-1{margin-top:var(--spacing,.25rem)}.mt-2{margin-top:calc(var(--spacing,.25rem) * 2)}.mt-3{margin-top:calc(var(--spacing,.25rem) * 3)}.mt-4{margin-top:calc(var(--spacing,.25rem) * 4)}.mt-5{margin-top:calc(var(--spacing,.25rem) * 5)}.mt-6{margin-top:calc(var(--spacing,.25rem) * 6)}.mr-2{margin-right:calc(var(--spacing,.25rem) * 2)}.mr-3{margin-right:calc(var(--spacing,.25rem) * 3)}.-mb-px{margin-bottom:-1px}.mb-1{margin-bottom:var(--spacing,.25rem)}.mb-3{margin-bottom:calc(var(--spacing,.25rem) * 3)}.mb-4{margin-bottom:calc(var(--spacing,.25rem) * 4)}.ml-1{margin-left:var(--spacing,.25rem)}.ml-2{margin-left:calc(var(--spacing,.25rem) * 2)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.h-1\.5{height:calc(var(--spacing,.25rem) * 1.5)}.h-2{height:calc(var(--spacing,.25rem) * 2)}.h-2\.5{height:calc(var(--spacing,.25rem) * 2.5)}.h-3{height:calc(var(--spacing,.25rem) * 3)}.h-3\.5{height:calc(var(--spacing,.25rem) * 3.5)}.h-4{height:calc(var(--spacing,.25rem) * 4)}.h-5{height:calc(var(--spacing,.25rem) * 5)}.h-6{height:calc(var(--spacing,.25rem) * 6)}.h-7{height:calc(var(--spacing,.25rem) * 7)}.h-8{height:calc(var(--spacing,.25rem) * 8)}.h-16{height:calc(var(--spacing,.25rem) * 16)}.max-h-48{max-height:calc(var(--spacing,.25rem) * 48)}.min-h-20{min-height:calc(var(--spacing,.25rem) * 20)}.min-h-40{min-height:calc(var(--spacing,.25rem) * 40)}.w-1\.5{width:calc(var(--spacing,.25rem) * 1.5)}.w-2{width:calc(var(--spacing,.25rem) * 2)}.w-2\.5{width:calc(var(--spacing,.25rem) * 2.5)}.w-3{width:calc(var(--spacing,.25rem) * 3)}.w-3\.5{width:calc(var(--spacing,.25rem) * 3.5)}.w-4{width:calc(var(--spacing,.25rem) * 4)}.w-5{width:calc(var(--spacing,.25rem) * 5)}.w-6{width:calc(var(--spacing,.25rem) * 6)}.w-7{width:calc(var(--spacing,.25rem) * 7)}.w-8{width:calc(var(--spacing,.25rem) * 8)}.w-10{width:calc(var(--spacing,.25rem) * 10)}.w-16{width:calc(var(--spacing,.25rem) * 16)}.w-64{width:calc(var(--spacing,.25rem) * 64)}.w-80{width:calc(var(--spacing,.25rem) * 80)}.w-full{width:100%}.max-w-32{max-width:calc(var(--spacing,.25rem) * 32)}.max-w-64{max-width:calc(var(--spacing,.25rem) * 64)}.max-w-\[calc\(100vw-3rem\)\]{max-width:calc(100vw - 3rem)}.min-w-0{min-width:0}.min-w-44{min-width:calc(var(--spacing,.25rem) * 44)}.min-w-48{min-width:calc(var(--spacing,.25rem) * 48)}.min-w-full{min-width:100%}.flex-1{flex:1}.shrink-0{flex-shrink:0}.table-auto{table-layout:auto}.animate-pulse{animation:var(--animate-pulse,pulse 2s cubic-bezier(.4, 0, .6, 1) infinite)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing,.25rem)}.gap-1\.5{gap:calc(var(--spacing,.25rem) * 1.5)}.gap-2{gap:calc(var(--spacing,.25rem) * 2)}.gap-3{gap:calc(var(--spacing,.25rem) * 3)}.gap-4{gap:calc(var(--spacing,.25rem) * 4)}.gap-6{gap:calc(var(--spacing,.25rem) * 6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(var(--spacing,.25rem) * var(--tw-space-y-reverse));margin-block-end:calc(var(--spacing,.25rem) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing,.25rem) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing,.25rem) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing,.25rem) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing,.25rem) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing,.25rem) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing,.25rem) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing,.25rem) * 5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing,.25rem) * 5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing,.25rem) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing,.25rem) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-x-3>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing,.25rem) * 3) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing,.25rem) * 3) * calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-5>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing,.25rem) * 5) * var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing,.25rem) * 5) * calc(1 - var(--tw-space-x-reverse)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-line-default>:not(:last-child)){border-color:var(--color-line-default)}:where(.divide-line-light>:not(:last-child)){border-color:var(--color-line-light)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg,.5rem)}.rounded-md{border-radius:var(--radius-md,.375rem)}.rounded-sm{border-radius:var(--radius-sm,.25rem)}.rounded-xl{border-radius:var(--radius-xl,.75rem)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-heading{border-color:var(--color-heading)}.border-line-default{border-color:var(--color-line-default)}.border-line-light{border-color:var(--color-line-light)}.border-line-strong{border-color:var(--color-line-strong)}.border-primary-200{border-color:var(--color-primary-200)}.border-primary-400{border-color:var(--color-primary-400)}.border-primary-500{border-color:var(--color-primary-500)}.border-status-yellow{border-color:var(--color-status-yellow)}.border-transparent{border-color:#0000}.bg-alert-error-bg{background-color:var(--color-alert-error-bg)}.bg-alert-success-bg\!{background-color:var(--color-alert-success-bg)!important}.bg-alert-warning-bg{background-color:var(--color-alert-warning-bg)}.bg-alert-warning-bg\!{background-color:var(--color-alert-warning-bg)!important}.bg-btn-primary{background-color:var(--color-btn-primary)}.bg-hover-strong{background-color:var(--color-hover-strong)}.bg-line-default{background-color:var(--color-line-default)}.bg-line-strong{background-color:var(--color-line-strong)}.bg-primary-50{background-color:var(--color-primary-50)}.bg-primary-50\!{background-color:var(--color-primary-50)!important}.bg-primary-500{background-color:var(--color-primary-500)}.bg-status-green{background-color:var(--color-status-green)}.bg-status-red{background-color:var(--color-status-red)}.bg-surface{background-color:var(--color-surface)}.bg-surface-secondary{background-color:var(--color-surface-secondary)}.bg-surface-tertiary{background-color:var(--color-surface-tertiary)}.bg-surface-tertiary\!{background-color:var(--color-surface-tertiary)!important}.bg-white{background-color:var(--color-white,#fff)}.bg-white\/20{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.bg-white\/20{background-color:color-mix(in oklab, var(--color-white,#fff) 20%, transparent)}}.p-1{padding:var(--spacing,.25rem)}.p-1\.5{padding:calc(var(--spacing,.25rem) * 1.5)}.p-2{padding:calc(var(--spacing,.25rem) * 2)}.p-3{padding:calc(var(--spacing,.25rem) * 3)}.p-5{padding:calc(var(--spacing,.25rem) * 5)}.px-1{padding-inline:var(--spacing,.25rem)}.px-1\.5{padding-inline:calc(var(--spacing,.25rem) * 1.5)}.px-2{padding-inline:calc(var(--spacing,.25rem) * 2)}.px-3{padding-inline:calc(var(--spacing,.25rem) * 3)}.px-4{padding-inline:calc(var(--spacing,.25rem) * 4)}.px-5{padding-inline:calc(var(--spacing,.25rem) * 5)}.px-6{padding-inline:calc(var(--spacing,.25rem) * 6)}.py-0\.5{padding-block:calc(var(--spacing,.25rem) * .5)}.py-1{padding-block:var(--spacing,.25rem)}.py-1\.5{padding-block:calc(var(--spacing,.25rem) * 1.5)}.py-2{padding-block:calc(var(--spacing,.25rem) * 2)}.py-2\.5{padding-block:calc(var(--spacing,.25rem) * 2.5)}.py-3{padding-block:calc(var(--spacing,.25rem) * 3)}.py-4{padding-block:calc(var(--spacing,.25rem) * 4)}.py-6{padding-block:calc(var(--spacing,.25rem) * 6)}.py-8{padding-block:calc(var(--spacing,.25rem) * 8)}.py-10{padding-block:calc(var(--spacing,.25rem) * 10)}.py-16{padding-block:calc(var(--spacing,.25rem) * 16)}.pt-2{padding-top:calc(var(--spacing,.25rem) * 2)}.pt-3{padding-top:calc(var(--spacing,.25rem) * 3)}.pb-2{padding-bottom:calc(var(--spacing,.25rem) * 2)}.pb-3{padding-bottom:calc(var(--spacing,.25rem) * 3)}.pb-4{padding-bottom:calc(var(--spacing,.25rem) * 4)}.pl-4{padding-left:calc(var(--spacing,.25rem) * 4)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.text-2xl{font-size:var(--text-2xl,1.5rem);line-height:var(--tw-leading,var(--text-2xl--line-height,calc(2 / 1.5)))}.text-base{font-size:var(--text-base,1rem);line-height:var(--tw-leading,var(--text-base--line-height,calc(1.5 / 1)))}.text-lg{font-size:var(--text-lg,1.125rem);line-height:var(--tw-leading,var(--text-lg--line-height,calc(1.75 / 1.125)))}.text-sm{font-size:var(--text-sm,.875rem);line-height:var(--tw-leading,var(--text-sm--line-height,calc(1.25 / .875)))}.text-xl{font-size:var(--text-xl,1.25rem);line-height:var(--tw-leading,var(--text-xl--line-height,calc(1.75 / 1.25)))}.text-xs{font-size:var(--text-xs,.75rem);line-height:var(--tw-leading,var(--text-xs--line-height,calc(1 / .75)))}.text-\[11px\]{font-size:11px}.leading-5{--tw-leading:calc(var(--spacing,.25rem) * 5);line-height:calc(var(--spacing,.25rem) * 5)}.font-medium{--tw-font-weight:var(--font-weight-medium,500);font-weight:var(--font-weight-medium,500)}.font-normal{--tw-font-weight:var(--font-weight-normal,400);font-weight:var(--font-weight-normal,400)}.font-semibold{--tw-font-weight:var(--font-weight-semibold,600);font-weight:var(--font-weight-semibold,600)}.tracking-wide{--tw-tracking:var(--tracking-wide,.025em);letter-spacing:var(--tracking-wide,.025em)}.tracking-wider{--tw-tracking:var(--tracking-wider,.05em);letter-spacing:var(--tracking-wider,.05em)}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.text-alert-error-text{color:var(--color-alert-error-text)}.text-alert-success-text\!{color:var(--color-alert-success-text)!important}.text-alert-warning-text{color:var(--color-alert-warning-text)}.text-alert-warning-text\!{color:var(--color-alert-warning-text)!important}.text-body{color:var(--color-body)}.text-heading{color:var(--color-heading)}.text-muted{color:var(--color-muted)}.text-muted\!{color:var(--color-muted)!important}.text-primary-500{color:var(--color-primary-500)}.text-primary-500\!{color:var(--color-primary-500)!important}.text-primary-600{color:var(--color-primary-600)}.text-primary-700{color:var(--color-primary-700)}.text-status-green{color:var(--color-status-green)}.text-status-red{color:var(--color-status-red)}.text-subtle{color:var(--color-subtle)}.text-white{color:var(--color-white,#fff)}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.opacity-40{opacity:.4}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline-hidden{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.outline-hidden{outline-offset:2px;outline:2px solid #0000}}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function,cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration,var(--default-transition-duration,.15s))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function,cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration,var(--default-transition-duration,.15s))}@media (hover:hover){.group-hover\:text-muted:is(:where(.group):hover *){color:var(--color-muted)}}.last\:border-r-0:last-child{border-right-style:var(--tw-border-style);border-right-width:0}@media (hover:hover){.hover\:border-line-strong:hover{border-color:var(--color-line-strong)}.hover\:border-primary-500:hover{border-color:var(--color-primary-500)}.hover\:bg-btn-primary-hover:hover{background-color:var(--color-btn-primary-hover)}.hover\:bg-hover:hover{background-color:var(--color-hover)}.hover\:bg-white\/20:hover{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/20:hover{background-color:color-mix(in oklab, var(--color-white,#fff) 20%, transparent)}}.hover\:text-alert-error-text:hover{color:var(--color-alert-error-text)}.hover\:text-body:hover{color:var(--color-body)}.hover\:text-heading:hover{color:var(--color-heading)}.hover\:text-primary-500:hover{color:var(--color-primary-500)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:border-primary-400:focus{border-color:var(--color-primary-400)}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-primary-400:focus{--tw-ring-color:var(--color-primary-400)}.focus\:outline-hidden:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.focus\:outline-hidden:focus{outline-offset:2px;outline:2px solid #0000}}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media not all and (width>=40rem){.max-sm\:hidden{display:none}}@media (width>=40rem){.sm\:w-48{width:calc(var(--spacing,.25rem) * 48)}.sm\:w-56{width:calc(var(--spacing,.25rem) * 56)}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (width>=48rem){.md\:h-9{height:calc(var(--spacing,.25rem) * 9)}.md\:px-3{padding-inline:calc(var(--spacing,.25rem) * 3)}}@media (width>=64rem){.lg\:mb-1{margin-bottom:var(--spacing,.25rem)}.lg\:block{display:block}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:flex-row{flex-direction:row}.lg\:items-end{align-items:flex-end}}@media (width>=80rem){.xl\:grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}} /*$vite$:1*/ \ No newline at end of file diff --git a/resources/js/api/billing.ts b/resources/js/api/billing.ts index d934516..baee174 100644 --- a/resources/js/api/billing.ts +++ b/resources/js/api/billing.ts @@ -2,7 +2,7 @@ import type { AxiosInstance } from 'axios' import type { Wrapped } from '@/types/api' import type { BillingCustomer, - BillingGrouping, + BillingSelection, CompanyInvoiceDefaults, ConfirmItem, CreatedInvoice, @@ -16,7 +16,7 @@ import type { const BASE = '/api/v1/tasks-projects' -/** The module endpoints the wizard talks to. */ +/** The module endpoints the invoicing flow talks to. */ export const BILLING_API = { customers: `${BASE}/billing/customers`, unbilled: `${BASE}/billing/unbilled`, @@ -33,16 +33,13 @@ export const BILLING_API = { */ export const HOST_BILLING_API = { bootstrap: '/api/v1/bootstrap', - customers: '/api/v1/customers', + customer: (customerId: number): string => `/api/v1/customers/${customerId}`, invoices: '/api/v1/invoices', invoiceTemplates: '/api/v1/invoices/templates', nextNumber: '/api/v1/next-number', exchangeRate: (currencyId: number): string => `/api/v1/currencies/${currencyId}/exchange-rate`, } as const -/** How many contacts the name lookup asks for. */ -export const CUSTOMER_LOOKUP_LIMIT = 200 - export interface UnbilledRange { /** `Y-m-d`, inclusive. */ from?: string @@ -75,24 +72,46 @@ export async function fetchUnbilledTime( return data.data } -/** The invoice body for a selection, plus the entries behind each line. */ +/** + * The invoice body for a selection, plus the entries behind each line. + * + * The selection arrives in whichever of the three shapes the calling screen + * knows and leaves as the one key the endpoint expects, because the rules + * refuse a body that names two of them. The grouping rides along only when the + * caller chose one, so the server's own default stays the default. + */ export async function prepareInvoice( client: AxiosInstance, - entryIds: number[], - grouping: BillingGrouping, + selection: BillingSelection, ): Promise { - const { data } = await client.post>(BILLING_API.prepare, { - entry_ids: entryIds, - grouping, - }) + const { data } = await client.post>( + BILLING_API.prepare, + prepareBody(selection), + ) return data.data } +/** The one selection key the request carries, plus the grouping when set. */ +function prepareBody(selection: BillingSelection): Record { + const body: Record = + 'taskIds' in selection + ? { task_ids: selection.taskIds } + : 'projectId' in selection + ? { project_id: selection.projectId } + : { entry_ids: selection.entryIds } + + if (selection.grouping !== undefined) { + body.grouping = selection.grouping + } + + return body +} + /** * Stamp the entries with the ids the host handed back. * - * Idempotent, so a wizard that created the invoice and then lost the stamp can + * Idempotent, so a flow that created the invoice and then lost the stamp can * offer the same call again rather than a second invoice. */ export async function confirmInvoice( @@ -108,16 +127,23 @@ export async function confirmInvoice( return data?.stamped ?? 0 } -/** The company's contacts, for turning a customer id into a name. */ -export async function listBillingCustomers( +/** + * One contact, read for the currency it settles in. + * + * The host's invoice endpoint compares the *contact's* currency with the + * company setting to decide whether an exchange rate is required, so the + * answer has to come from the contact rather than from the currency the time + * happened to be logged in. + */ +export async function fetchBillingCustomer( client: AxiosInstance, - limit = CUSTOMER_LOOKUP_LIMIT, -): Promise { - const { data } = await client.get>(HOST_BILLING_API.customers, { - params: { limit }, - }) + customerId: number, +): Promise { + const { data } = await client.get>( + HOST_BILLING_API.customer(customerId), + ) - return data.data ?? [] + return data?.data ?? null } /** Create the draft invoice with the session's own client. */ diff --git a/resources/js/components/BulkActionBar.vue b/resources/js/components/BulkActionBar.vue index 8151d1c..fce0df8 100644 --- a/resources/js/components/BulkActionBar.vue +++ b/resources/js/components/BulkActionBar.vue @@ -4,17 +4,25 @@ import { useTranslate } from '@/support/i18n' import type { SelectOption } from '@/types/board' import type { TaskStatus } from '@/types/task-status' -const props = defineProps<{ - /** How many tasks the selection holds. The bar hides at zero. */ - count: number - statuses: TaskStatus[] - /** True while a bulk request is in flight. */ - busy: boolean -}>() +const props = withDefaults( + defineProps<{ + /** How many tasks the selection holds. The bar hides at zero. */ + count: number + statuses: TaskStatus[] + /** True while a bulk request is in flight. */ + busy: boolean + /** True while the invoicing sequence is running, anywhere in the module. */ + invoicing?: boolean + /** False once the server has refused the ability to invoice. */ + canInvoice?: boolean + }>(), + { invoicing: false, canInvoice: true }, +) const emit = defineEmits<{ (event: 'status', statusId: number): void (event: 'delete'): void + (event: 'invoice'): void (event: 'clear'): void (event: 'select-page'): void }>() @@ -63,16 +71,19 @@ watch(status, (option) => { {{ t('tasks_projects.tasks.bulk.delete') }} - - - - - {{ t('tasks_projects.tasks.bulk.invoice') }} - - + + + {{ t('tasks_projects.tasks.bulk.invoice') }} +