1012 lines
100 KiB
JavaScript
1012 lines
100 KiB
JavaScript
import { defineComponent, computed, mergeProps, useSSRContext, ref, reactive, watch, unref } from "vue";
|
||
import { ssrRenderAttrs, ssrInterpolate, ssrRenderList, ssrRenderClass, ssrRenderStyle, ssrIncludeBooleanAttr, ssrLooseContain, ssrLooseEqual, ssrRenderAttr, ssrRenderComponent } from "vue/server-renderer";
|
||
import { c as useAuthStore, d as useCookie } from "../server.mjs";
|
||
import { useRoute, useRouter } from "vue-router";
|
||
import "/app/node_modules/ofetch/dist/node.mjs";
|
||
import "#internal/nuxt/paths";
|
||
import "/app/node_modules/hookable/dist/index.mjs";
|
||
import "/app/node_modules/unctx/dist/index.mjs";
|
||
import "/app/node_modules/h3/dist/index.mjs";
|
||
import "pinia";
|
||
import "/app/node_modules/defu/dist/defu.mjs";
|
||
import "/app/node_modules/ufo/dist/index.mjs";
|
||
import "/app/node_modules/klona/dist/index.mjs";
|
||
import "/app/node_modules/cookie-es/dist/index.mjs";
|
||
import "/app/node_modules/destr/dist/index.mjs";
|
||
import "/app/node_modules/ohash/dist/index.mjs";
|
||
import "/app/node_modules/@unhead/vue/dist/index.mjs";
|
||
import "@vue/devtools-api";
|
||
const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
||
__name: "GarageGeneralTab",
|
||
__ssrInlineRender: true,
|
||
props: {
|
||
garage: {}
|
||
},
|
||
setup(__props) {
|
||
const props = __props;
|
||
function orgTypeLabel(type) {
|
||
const map = {
|
||
dealership: "Dealership",
|
||
service: "Service Center",
|
||
rental: "Rental Agency",
|
||
fleet: "Fleet Operator",
|
||
individual: "Individual",
|
||
workshop: "Workshop",
|
||
garage: "Garage",
|
||
other: "Other"
|
||
};
|
||
return map[type?.toLowerCase()] || type || "-";
|
||
}
|
||
function formatDate(dateStr) {
|
||
if (!dateStr) return "-";
|
||
try {
|
||
return new Intl.DateTimeFormat("hu-HU", {
|
||
year: "numeric",
|
||
month: "2-digit",
|
||
day: "2-digit"
|
||
}).format(new Date(dateStr));
|
||
} catch {
|
||
return dateStr;
|
||
}
|
||
}
|
||
const formattedAddress = computed(() => {
|
||
if (!props.garage) return "";
|
||
const parts = [
|
||
props.garage.address_zip,
|
||
props.garage.address_city,
|
||
props.garage.address_street_name,
|
||
props.garage.address_street_type,
|
||
props.garage.address_house_number
|
||
].filter(Boolean);
|
||
return parts.join(" ") || "-";
|
||
});
|
||
const formattedBillingAddress = computed(() => {
|
||
if (!props.garage) return "";
|
||
const parts = [
|
||
props.garage.billing_zip,
|
||
props.garage.billing_city,
|
||
props.garage.billing_street_name,
|
||
props.garage.billing_street_type,
|
||
props.garage.billing_house_number
|
||
].filter(Boolean);
|
||
return parts.join(" ") || "";
|
||
});
|
||
const formattedNotificationAddress = computed(() => {
|
||
if (!props.garage) return "";
|
||
const parts = [
|
||
props.garage.notification_zip,
|
||
props.garage.notification_city,
|
||
props.garage.notification_street_name,
|
||
props.garage.notification_street_type,
|
||
props.garage.notification_house_number
|
||
].filter(Boolean);
|
||
return parts.join(" ") || "";
|
||
});
|
||
return (_ctx, _push, _parent, _attrs) => {
|
||
_push(`<div${ssrRenderAttrs(mergeProps({ class: "space-y-6" }, _attrs))}><div class="bg-slate-800/50 border border-slate-700 rounded-xl overflow-hidden"><div class="px-6 py-4 border-b border-slate-700 flex items-center gap-3"><div class="p-2 rounded-lg bg-indigo-500/10 text-indigo-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"></path></svg></div><h3 class="text-base font-semibold text-white">${ssrInterpolate(_ctx.$t("garages.details.company_info"))}</h3></div><div class="px-6 py-5"><div class="grid grid-cols-1 md:grid-cols-2 gap-6"><div class="space-y-4"><div><p class="text-xs text-slate-500 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.details.company_name"))}</p><p class="text-sm text-white mt-1">${ssrInterpolate(__props.garage.full_name)}</p></div><div><p class="text-xs text-slate-500 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.details.display_name"))}</p><p class="text-sm text-white mt-1">${ssrInterpolate(__props.garage.display_name || "—")}</p></div><div><p class="text-xs text-slate-500 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.details.org_type"))}</p><p class="text-sm text-white mt-1">${ssrInterpolate(orgTypeLabel(__props.garage.org_type))}</p></div></div><div class="space-y-4"><div><p class="text-xs text-slate-500 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.details.tax_number"))}</p><p class="text-sm text-white mt-1">${ssrInterpolate(__props.garage.tax_number || "—")}</p></div><div><p class="text-xs text-slate-500 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.details.reg_number"))}</p><p class="text-sm text-white mt-1">${ssrInterpolate(__props.garage.reg_number || "—")}</p></div><div><p class="text-xs text-slate-500 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.details.created_at"))}</p><p class="text-sm text-white mt-1">${ssrInterpolate(formatDate(__props.garage.created_at))}</p></div></div></div><div class="mt-6 pt-6 border-t border-slate-700/50"><p class="text-xs text-slate-500 uppercase tracking-wider mb-3">${ssrInterpolate(_ctx.$t("garages.details.address"))}</p><p class="text-sm text-white">${ssrInterpolate(formattedAddress.value)}</p></div>`);
|
||
if (formattedBillingAddress.value) {
|
||
_push(`<div class="mt-4 pt-4 border-t border-slate-700/50"><p class="text-xs text-slate-500 uppercase tracking-wider mb-3">${ssrInterpolate(_ctx.$t("garages.details.billing_address"))}</p><p class="text-sm text-white">${ssrInterpolate(formattedBillingAddress.value)}</p></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (formattedNotificationAddress.value) {
|
||
_push(`<div class="mt-4 pt-4 border-t border-slate-700/50"><p class="text-xs text-slate-500 uppercase tracking-wider mb-3">${ssrInterpolate(_ctx.$t("garages.details.notification_address"))}</p><p class="text-sm text-white">${ssrInterpolate(formattedNotificationAddress.value)}</p></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`<div class="mt-6 pt-4 border-t border-slate-700/50"><p class="text-xs text-slate-500 uppercase tracking-wider mb-3">Rendszer Azonosítók</p><div class="flex gap-6 text-xs font-mono text-slate-500"><span>Garázs ID: <span class="text-slate-400">${ssrInterpolate(__props.garage.id)}</span></span><span>User ID: <span class="text-slate-400">${ssrInterpolate(__props.garage.owner_user_id ?? "N/A")}</span></span><span>Person ID: <span class="text-slate-400">${ssrInterpolate(__props.garage.owner_person_id ?? "N/A")}</span></span></div></div></div></div><div class="bg-slate-800/50 border border-slate-700 rounded-xl overflow-hidden"><div class="px-6 py-4 border-b border-slate-700 flex items-center gap-3"><div class="p-2 rounded-lg bg-emerald-500/10 text-emerald-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"></path></svg></div><h3 class="text-base font-semibold text-white">${ssrInterpolate(_ctx.$t("garages.details.contact_info"))}</h3></div><div class="px-6 py-5">`);
|
||
if (__props.garage.contact_person_name || __props.garage.contact_email || __props.garage.contact_phone || __props.garage.primary_contact) {
|
||
_push(`<div class="grid grid-cols-1 md:grid-cols-2 gap-6"><div class="space-y-4"><div><p class="text-xs text-slate-500 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.details.contact_name"))}</p><p class="text-sm text-white mt-1 font-medium">${ssrInterpolate(__props.garage.contact_person_name || __props.garage.primary_contact?.full_name || "—")}</p></div><div><p class="text-xs text-slate-500 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.details.contact_email"))}</p><p class="text-sm text-white mt-1 flex items-center gap-1.5"><svg class="w-4 h-4 text-slate-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path></svg><span>${ssrInterpolate(__props.garage.contact_email || __props.garage.primary_contact?.email || "—")}</span></p></div></div><div class="space-y-4"><div><p class="text-xs text-slate-500 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.details.contact_phone"))}</p><p class="text-sm text-white mt-1 flex items-center gap-1.5"><svg class="w-4 h-4 text-slate-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"></path></svg><span>${ssrInterpolate(__props.garage.contact_phone || __props.garage.primary_contact?.phone || "—")}</span></p></div>`);
|
||
if (__props.garage.primary_contact?.role || __props.garage.primary_contact?.department) {
|
||
_push(`<div><p class="text-xs text-slate-500 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.details.contact_role"))}</p><p class="text-sm text-white mt-1">${ssrInterpolate(__props.garage.primary_contact.role || "—")}`);
|
||
if (__props.garage.primary_contact?.department) {
|
||
_push(`<span> · ${ssrInterpolate(__props.garage.primary_contact.department)}</span>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</p></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</div></div>`);
|
||
} else {
|
||
_push(`<div class="text-center py-4"><p class="text-sm text-slate-400">${ssrInterpolate(_ctx.$t("garages.details.no_contact"))}</p></div>`);
|
||
}
|
||
_push(`</div></div></div>`);
|
||
};
|
||
}
|
||
});
|
||
const _sfc_setup$3 = _sfc_main$3.setup;
|
||
_sfc_main$3.setup = (props, ctx) => {
|
||
const ssrContext = useSSRContext();
|
||
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/garages/GarageGeneralTab.vue");
|
||
return _sfc_setup$3 ? _sfc_setup$3(props, ctx) : void 0;
|
||
};
|
||
const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
||
__name: "GarageFleetTab",
|
||
__ssrInlineRender: true,
|
||
props: {
|
||
garage: {},
|
||
orgId: {},
|
||
fleetVehicles: {},
|
||
fleetLoading: { type: Boolean }
|
||
},
|
||
setup(__props) {
|
||
const props = __props;
|
||
const auth = useAuthStore();
|
||
function hasOrgPermission(perm) {
|
||
if (auth.isAdmin) return true;
|
||
if (auth.user?.system_capabilities?.[perm]) return true;
|
||
if (auth.user?.org_capabilities?.[props.orgId]?.[perm]) return true;
|
||
return false;
|
||
}
|
||
function fleetStatusLabel(status) {
|
||
const map = {
|
||
active: "Active",
|
||
inactive: "Inactive",
|
||
sold: "Sold",
|
||
scrapped: "Scrapped",
|
||
pending: "Pending",
|
||
draft: "Draft"
|
||
};
|
||
return map[status?.toLowerCase()] || status || "Unknown";
|
||
}
|
||
function fleetStatusBadgeClass(status) {
|
||
const map = {
|
||
active: "bg-green-500/10 text-green-400",
|
||
inactive: "bg-gray-500/10 text-gray-400",
|
||
sold: "bg-red-500/10 text-red-400",
|
||
scrapped: "bg-red-500/10 text-red-400",
|
||
pending: "bg-yellow-500/10 text-yellow-400",
|
||
draft: "bg-gray-500/10 text-gray-400"
|
||
};
|
||
return map[status?.toLowerCase()] || "bg-gray-500/10 text-gray-400";
|
||
}
|
||
function fleetStatusDotClass(status) {
|
||
const map = {
|
||
active: "bg-green-400",
|
||
inactive: "bg-gray-400",
|
||
sold: "bg-red-400",
|
||
scrapped: "bg-red-400",
|
||
pending: "bg-yellow-400",
|
||
draft: "bg-gray-400"
|
||
};
|
||
return map[status?.toLowerCase()] || "bg-gray-400";
|
||
}
|
||
return (_ctx, _push, _parent, _attrs) => {
|
||
_push(`<div${ssrRenderAttrs(mergeProps({ class: "space-y-6" }, _attrs))}>`);
|
||
if (hasOrgPermission("fleet:view")) {
|
||
_push(`<!--[--><div class="flex items-center justify-between"><div class="flex items-center gap-3"><div class="p-2 rounded-lg bg-indigo-500/10 text-indigo-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 17a2 2 0 11-4 0 2 2 0 014 0zM19 17a2 2 0 11-4 0 2 2 0 014 0z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16V6a1 1 0 00-1-1H4a1 1 0 00-1 1v10a1 1 0 001 1h1m8-1a1 1 0 01-1 1H9m4-1V8a1 1 0 011-1h2.586a1 1 0 01.707.293l3.414 3.414a1 1 0 01.293.707V16a1 1 0 01-1 1h-1m-6-1a1 1 0 001 1h1M5 17a2 2 0 104 0m-4 0a2 2 0 114 0m6 0a2 2 0 104 0m-4 0a2 2 0 114 0"></path></svg></div><div><h3 class="text-base font-semibold text-white">${ssrInterpolate(_ctx.$t("garages.fleet.title"))}</h3><p class="text-xs text-slate-400 mt-0.5">${ssrInterpolate(_ctx.$t("garages.fleet.total_vehicles", { count: __props.fleetVehicles.length }))}</p></div></div></div><div class="bg-slate-800/50 border border-slate-700 rounded-xl overflow-hidden"><div class="overflow-x-auto"><table class="w-full text-sm"><thead><tr class="border-b border-slate-700"><th class="text-left px-4 py-3 text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.fleet.plate"))}</th><th class="text-left px-4 py-3 text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.fleet.brand_model"))}</th><th class="text-left px-4 py-3 text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.fleet.year"))}</th><th class="text-left px-4 py-3 text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.fleet.vin"))}</th><th class="text-left px-4 py-3 text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.fleet.status"))}</th></tr></thead><tbody><!--[-->`);
|
||
ssrRenderList(__props.fleetVehicles, (v) => {
|
||
_push(`<tr class="border-b border-slate-700/50 last:border-b-0 hover:bg-slate-700/30 transition"><td class="px-4 py-3"><span class="text-sm font-bold text-white">${ssrInterpolate(v.license_plate || "—")}</span></td><td class="px-4 py-3"><span class="text-sm text-slate-300">${ssrInterpolate(v.brand || "—")}</span>`);
|
||
if (v.brand && v.model) {
|
||
_push(`<span class="text-slate-500 mx-1">·</span>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (v.model) {
|
||
_push(`<span class="text-sm text-slate-300">${ssrInterpolate(v.model)}</span>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</td><td class="px-4 py-3 text-sm text-slate-300">${ssrInterpolate(v.year || "—")}</td><td class="px-4 py-3"><span class="text-xs font-mono text-slate-400">${ssrInterpolate(v.vin || "—")}</span></td><td class="px-4 py-3"><span class="${ssrRenderClass([fleetStatusBadgeClass(v.status), "inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium"])}"><span class="${ssrRenderClass([fleetStatusDotClass(v.status), "w-1.5 h-1.5 rounded-full"])}"></span> ${ssrInterpolate(fleetStatusLabel(v.status))}</span></td></tr>`);
|
||
});
|
||
_push(`<!--]-->`);
|
||
if (__props.fleetVehicles.length === 0 && !__props.fleetLoading) {
|
||
_push(`<tr><td colspan="5" class="px-4 py-12 text-center"><svg class="w-12 h-12 text-slate-600 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9 17a2 2 0 11-4 0 2 2 0 014 0zM19 17a2 2 0 11-4 0 2 2 0 014 0z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13 16V6a1 1 0 00-1-1H4a1 1 0 00-1 1v10a1 1 0 001 1h1m8-1a1 1 0 01-1 1H9m4-1V8a1 1 0 011-1h2.586a1 1 0 01.707.293l3.414 3.414a1 1 0 01.293.707V16a1 1 0 01-1 1h-1m-6-1a1 1 0 001 1h1M5 17a2 2 0 104 0m-4 0a2 2 0 114 0m6 0a2 2 0 104 0m-4 0a2 2 0 114 0"></path></svg><p class="text-sm text-slate-400">${ssrInterpolate(_ctx.$t("garages.fleet.no_vehicles"))}</p></td></tr>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (__props.fleetLoading) {
|
||
_push(`<tr><td colspan="5" class="px-4 py-12 text-center"><svg class="w-8 h-8 text-indigo-400 animate-spin mx-auto" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg><p class="text-sm text-slate-400 mt-2">${ssrInterpolate(_ctx.$t("garages.details.loading"))}</p></td></tr>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</tbody></table></div></div><!--]-->`);
|
||
} else {
|
||
_push(`<div class="bg-slate-800/50 border border-slate-700 rounded-xl p-12 text-center"><svg class="w-12 h-12 text-slate-600 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636"></path></svg><p class="text-sm text-slate-400">${ssrInterpolate(_ctx.$t("garages.fleet.no_fleet_access"))}</p></div>`);
|
||
}
|
||
_push(`</div>`);
|
||
};
|
||
}
|
||
});
|
||
const _sfc_setup$2 = _sfc_main$2.setup;
|
||
_sfc_main$2.setup = (props, ctx) => {
|
||
const ssrContext = useSSRContext();
|
||
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/garages/GarageFleetTab.vue");
|
||
return _sfc_setup$2 ? _sfc_setup$2(props, ctx) : void 0;
|
||
};
|
||
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
||
__name: "GarageSubscriptionTab",
|
||
__ssrInlineRender: true,
|
||
props: {
|
||
garage: {},
|
||
fleetVehicles: {}
|
||
},
|
||
emits: ["refresh"],
|
||
setup(__props, { expose: __expose, emit: __emit }) {
|
||
const props = __props;
|
||
const auth = useAuthStore();
|
||
const availableTiers = ref([]);
|
||
const selectedTierId = ref("");
|
||
const customExpiresAt = ref("");
|
||
const subscriptionSaving = ref(false);
|
||
const subscriptionSaveError = ref(null);
|
||
const extraVehicles = ref(0);
|
||
const extraBranches = ref(0);
|
||
const extraUsers = ref(0);
|
||
const addonDates = reactive({
|
||
vehicles: "",
|
||
branches: "",
|
||
users: ""
|
||
});
|
||
function syncAddonFromSubscription() {
|
||
const sub = props.garage?.subscription;
|
||
if (!sub) return;
|
||
const allowances = sub.extra_allowances || {};
|
||
extraVehicles.value = allowances.extra_vehicles ?? 0;
|
||
extraBranches.value = allowances.extra_branches ?? 0;
|
||
extraUsers.value = allowances.extra_users ?? 0;
|
||
if (sub.addons?.length) {
|
||
for (const addon of sub.addons) {
|
||
if (addon.type === "extra_vehicles" && addon.expires_at) {
|
||
addonDates.vehicles = addon.expires_at.slice(0, 10);
|
||
} else if (addon.type === "extra_branches" && addon.expires_at) {
|
||
addonDates.branches = addon.expires_at.slice(0, 10);
|
||
} else if (addon.type === "extra_users" && addon.expires_at) {
|
||
addonDates.users = addon.expires_at.slice(0, 10);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
watch(() => props.garage?.subscription, (newSub) => {
|
||
if (newSub) {
|
||
syncAddonFromSubscription();
|
||
}
|
||
}, { immediate: true });
|
||
const vehicleQuotaLimit = computed(() => {
|
||
if (!props.garage?.subscription?.asset_limit) return 5;
|
||
return props.garage.subscription.asset_limit;
|
||
});
|
||
const vehicleQuotaPercent = computed(() => {
|
||
const limit = vehicleQuotaLimit.value;
|
||
if (limit <= 0) return 0;
|
||
return Math.min(100, Math.round(props.fleetVehicles.length / limit * 100));
|
||
});
|
||
const branchQuotaPercent = computed(() => {
|
||
const branches = props.garage?.branches?.length || 0;
|
||
const limit = props.garage?.subscription?.branch_limit;
|
||
if (!limit || limit <= 0) return 0;
|
||
return Math.min(100, Math.round(branches / limit * 100));
|
||
});
|
||
const employeeQuotaPercent = computed(() => {
|
||
const count = props.garage?.member_count || 0;
|
||
const limit = props.garage?.subscription?.user_limit;
|
||
if (!limit || limit <= 0) return 0;
|
||
return Math.min(100, Math.round(count / limit * 100));
|
||
});
|
||
const addonsChanged = computed(() => {
|
||
if (!props.garage?.subscription) return false;
|
||
const sub = props.garage.subscription;
|
||
const baselineVehicles = sub.extra_allowances?.extra_vehicles ?? 0;
|
||
const baselineBranches = sub.extra_allowances?.extra_branches ?? 0;
|
||
const baselineUsers = sub.extra_allowances?.extra_users ?? 0;
|
||
return extraVehicles.value !== baselineVehicles || extraBranches.value !== baselineBranches || extraUsers.value !== baselineUsers;
|
||
});
|
||
function formatChanges(hist) {
|
||
if (!hist) return null;
|
||
const oldData = hist.old_data || {};
|
||
const newData = hist.new_data || {};
|
||
const lines = [];
|
||
if (hist.action === "SUBSCRIPTION_TIER_CHANGE") {
|
||
const oldTier = oldData.tier_id;
|
||
const newTier = newData.tier_id;
|
||
const newTierName = newData.tier_name;
|
||
if (oldTier !== void 0 || newTier !== void 0) {
|
||
lines.push(`Csomag: #${oldTier ?? "?"} → ${newTierName ?? "#" + newTier}`);
|
||
}
|
||
const oldAddons = oldData.addons || {};
|
||
const newAddons = newData.addons || {};
|
||
for (const key of ["extra_vehicles", "extra_branches", "extra_users"]) {
|
||
const oldVal = oldAddons[key] ?? 0;
|
||
const newVal = newAddons[key] ?? 0;
|
||
if (oldVal !== newVal) {
|
||
const label = key === "extra_vehicles" ? "Extra Jármű" : key === "extra_branches" ? "Extra Telephely" : "Extra Dolgozó";
|
||
lines.push(`${label}: ${oldVal} → ${newVal}`);
|
||
}
|
||
}
|
||
return lines.length > 0 ? lines : null;
|
||
}
|
||
if (hist.action === "SUBSCRIPTION_ADDON_OVERRIDE") {
|
||
const oldAddons = oldData.addons || {};
|
||
const newAddons = newData.addons || {};
|
||
let hasChanges = false;
|
||
for (const key of ["extra_vehicles", "extra_branches", "extra_users"]) {
|
||
const oldVal = oldAddons[key] ?? 0;
|
||
const newVal = newAddons[key] ?? 0;
|
||
if (oldVal !== newVal) {
|
||
hasChanges = true;
|
||
const label = key === "extra_vehicles" ? "Extra Jármű" : key === "extra_branches" ? "Extra Telephely" : "Extra Dolgozó";
|
||
lines.push(`${label}: ${oldVal} → ${newVal}`);
|
||
}
|
||
}
|
||
return hasChanges ? lines : null;
|
||
}
|
||
const allKeys = /* @__PURE__ */ new Set([...Object.keys(oldData), ...Object.keys(newData)]);
|
||
for (const key of allKeys) {
|
||
if (key === "addons") continue;
|
||
const oldVal = JSON.stringify(oldData[key] ?? null);
|
||
const newVal = JSON.stringify(newData[key] ?? null);
|
||
if (oldVal !== newVal) {
|
||
lines.push(`${key}: ${oldVal} → ${newVal}`);
|
||
}
|
||
}
|
||
return lines.length > 0 ? lines : null;
|
||
}
|
||
function formatDate(dateStr) {
|
||
if (!dateStr) return "-";
|
||
try {
|
||
return new Intl.DateTimeFormat("hu-HU", {
|
||
year: "numeric",
|
||
month: "2-digit",
|
||
day: "2-digit"
|
||
}).format(new Date(dateStr));
|
||
} catch {
|
||
return dateStr;
|
||
}
|
||
}
|
||
function addonLabel(type) {
|
||
const map = {
|
||
extra_vehicles: "Extra Jármű",
|
||
extra_branches: "Extra Telephely",
|
||
extra_users: "Extra Dolgozó"
|
||
};
|
||
return map[type] || type;
|
||
}
|
||
function tierBadgeClass(tier) {
|
||
const map = {
|
||
basic: "bg-gray-100 text-gray-800",
|
||
premium: "bg-yellow-100 text-yellow-800",
|
||
enterprise: "bg-purple-100 text-purple-800",
|
||
trial: "bg-blue-100 text-blue-800"
|
||
};
|
||
return map[tier?.toLowerCase()] || "bg-gray-100 text-gray-800";
|
||
}
|
||
function statusLabel(status) {
|
||
const map = {
|
||
active: "Active",
|
||
inactive: "Inactive",
|
||
suspended: "Suspended",
|
||
pending: "Pending"
|
||
};
|
||
return map[status?.toLowerCase()] || status;
|
||
}
|
||
function statusBadgeClass(status) {
|
||
const map = {
|
||
active: "bg-green-100 text-green-800",
|
||
inactive: "bg-gray-100 text-gray-800",
|
||
suspended: "bg-red-100 text-red-800",
|
||
pending: "bg-yellow-100 text-yellow-800"
|
||
};
|
||
return map[status?.toLowerCase()] || "bg-gray-100 text-gray-800";
|
||
}
|
||
function statusDotClass(status) {
|
||
const map = {
|
||
active: "bg-green-400",
|
||
inactive: "bg-gray-400",
|
||
suspended: "bg-red-400",
|
||
pending: "bg-yellow-400"
|
||
};
|
||
return map[status?.toLowerCase()] || "bg-gray-400";
|
||
}
|
||
async function fetchTiers() {
|
||
try {
|
||
const tokenCookie = useCookie("access_token");
|
||
const token = (tokenCookie.value || auth.token || "").trim();
|
||
console.log("[GarageSubscriptionTab] Fetching tiers...");
|
||
const res = await fetch("/api/v1/admin/packages?include_hidden=true&limit=100", {
|
||
headers: {
|
||
"Authorization": `Bearer ${token}`,
|
||
"Content-Type": "application/json"
|
||
}
|
||
});
|
||
if (!res.ok) {
|
||
const errBody = await res.text().catch(() => "");
|
||
console.error(`[GarageSubscriptionTab] Fetch tiers failed: ${res.status} ${res.statusText}`, errBody);
|
||
throw new Error(`Failed to fetch tiers: ${res.status} ${errBody}`);
|
||
}
|
||
const data = await res.json();
|
||
console.log("[GarageSubscriptionTab] Fetched tiers response:", JSON.stringify(data));
|
||
availableTiers.value = data.tiers || [];
|
||
console.log("[GarageSubscriptionTab] availableTiers set:", availableTiers.value.length, "items");
|
||
} catch (e) {
|
||
console.error("[GarageSubscriptionTab] Failed to fetch tiers:", e);
|
||
subscriptionSaveError.value = `Hiba a csomagok betöltésekor: ${e.message}`;
|
||
}
|
||
}
|
||
__expose({ fetchTiers });
|
||
return (_ctx, _push, _parent, _attrs) => {
|
||
_push(`<div${ssrRenderAttrs(mergeProps({ class: "space-y-6" }, _attrs))}><div class="bg-slate-800/50 border border-slate-700 rounded-xl overflow-hidden"><div class="px-6 py-4 border-b border-slate-700 flex items-center gap-3"><div class="p-2 rounded-lg bg-amber-500/10 text-amber-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"></path></svg></div><h3 class="text-base font-semibold text-white">${ssrInterpolate(_ctx.$t("garages.details.subscription_info"))}</h3></div><div class="px-6 py-5">`);
|
||
if (__props.garage.subscription) {
|
||
_push(`<div class="grid grid-cols-2 md:grid-cols-4 gap-4"><div class="bg-slate-900/30 rounded-lg p-3"><p class="text-xs text-slate-500 uppercase tracking-wider mb-1">${ssrInterpolate(_ctx.$t("garages.details.tier_name"))}</p><span class="${ssrRenderClass([tierBadgeClass(__props.garage.subscription.tier_name), "inline-flex px-2.5 py-0.5 rounded-full text-xs font-medium"])}">${ssrInterpolate(__props.garage.subscription.tier_name)}</span></div><div class="bg-slate-900/30 rounded-lg p-3"><p class="text-xs text-slate-500 uppercase tracking-wider mb-1">${ssrInterpolate(_ctx.$t("garages.details.tier_level"))}</p><p class="text-sm font-semibold text-white">${ssrInterpolate(_ctx.$t("garages.details.level_n", { n: __props.garage.subscription.tier_level }))}</p></div><div class="bg-slate-900/30 rounded-lg p-3"><p class="text-xs text-slate-500 uppercase tracking-wider mb-1">${ssrInterpolate(_ctx.$t("garages.details.expires_at"))}</p>`);
|
||
if (__props.garage.subscription.expires_at) {
|
||
_push(`<p class="text-sm font-semibold text-white">${ssrInterpolate(formatDate(__props.garage.subscription.expires_at))}</p>`);
|
||
} else {
|
||
_push(`<p class="text-sm text-slate-400 italic">${ssrInterpolate(_ctx.$t("garages.indefinite"))}</p>`);
|
||
}
|
||
_push(`</div><div class="bg-slate-900/30 rounded-lg p-3"><p class="text-xs text-slate-500 uppercase tracking-wider mb-1">${ssrInterpolate(_ctx.$t("garages.details.asset_limit"))}</p><p class="text-sm font-semibold text-white">${ssrInterpolate(__props.garage.subscription.asset_limit)} ${ssrInterpolate(_ctx.$t("garages.details.vehicles"))}</p></div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (__props.garage.subscription) {
|
||
_push(`<div class="mt-4 grid grid-cols-2 gap-4"><div class="bg-slate-900/30 rounded-lg p-3"><p class="text-xs text-slate-500 uppercase tracking-wider mb-1">${ssrInterpolate(_ctx.$t("garages.details.vehicles_used"))}</p><p class="text-sm font-semibold text-white">${ssrInterpolate(__props.fleetVehicles.length)} / ${ssrInterpolate(__props.garage.subscription?.asset_limit ?? "∞")}</p><div class="mt-2 w-full h-1.5 bg-slate-700 rounded-full overflow-hidden"><div class="${ssrRenderClass([vehicleQuotaPercent.value >= 90 ? "bg-red-500" : vehicleQuotaPercent.value >= 70 ? "bg-amber-500" : "bg-blue-500", "h-full rounded-full transition-all duration-500"])}" style="${ssrRenderStyle({ width: Math.min(100, vehicleQuotaPercent.value) + "%" })}"></div></div></div><div class="bg-slate-900/30 rounded-lg p-3"><p class="text-xs text-slate-500 uppercase tracking-wider mb-1">${ssrInterpolate(_ctx.$t("garages.details.branches_used"))}</p><p class="text-sm font-semibold text-white">${ssrInterpolate(__props.garage.branches?.length || 0)} / ${ssrInterpolate(__props.garage.subscription?.branch_limit ?? "∞")}</p><div class="mt-2 w-full h-1.5 bg-slate-700 rounded-full overflow-hidden"><div class="${ssrRenderClass([branchQuotaPercent.value >= 90 ? "bg-red-500" : branchQuotaPercent.value >= 70 ? "bg-amber-500" : "bg-emerald-500", "h-full rounded-full transition-all duration-500"])}" style="${ssrRenderStyle({ width: Math.min(100, branchQuotaPercent.value) + "%" })}"></div></div></div><div class="bg-slate-900/30 rounded-lg p-3"><p class="text-xs text-slate-500 uppercase tracking-wider mb-1">${ssrInterpolate(_ctx.$t("garages.details.employees_used"))}</p><p class="text-sm font-semibold text-white">${ssrInterpolate(__props.garage.member_count || 0)} / ${ssrInterpolate(__props.garage.subscription?.user_limit && __props.garage.subscription.user_limit > 0 ? __props.garage.subscription.user_limit : "∞")}</p>`);
|
||
if (__props.garage.subscription?.user_limit && __props.garage.subscription.user_limit > 0) {
|
||
_push(`<div class="mt-2 w-full h-1.5 bg-slate-700 rounded-full overflow-hidden"><div class="${ssrRenderClass([employeeQuotaPercent.value >= 90 ? "bg-red-500" : employeeQuotaPercent.value >= 70 ? "bg-amber-500" : "bg-purple-500", "h-full rounded-full transition-all duration-500"])}" style="${ssrRenderStyle({ width: Math.min(100, employeeQuotaPercent.value) + "%" })}"></div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</div><div class="bg-slate-900/30 rounded-lg p-3 flex flex-col justify-center"><p class="text-xs text-slate-500 uppercase tracking-wider mb-1">${ssrInterpolate(_ctx.$t("garages.details.status"))}</p><span class="${ssrRenderClass([statusBadgeClass(__props.garage.status), "inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium self-start"])}"><span class="${ssrRenderClass([statusDotClass(__props.garage.status), "w-1.5 h-1.5 rounded-full"])}"></span> ${ssrInterpolate(statusLabel(__props.garage.status))}</span></div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (__props.garage.subscription?.addons?.length) {
|
||
_push(`<div class="mt-4 border-t border-slate-700/50 pt-4"><p class="text-xs text-slate-500 uppercase tracking-wider mb-3">${ssrInterpolate(_ctx.$t("garages.active_addons"))}</p><div class="overflow-hidden border border-slate-700/50 rounded-lg"><table class="w-full text-sm"><thead><tr class="bg-slate-900/40"><th class="px-3 py-2 text-left text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.addon_type"))}</th><th class="px-3 py-2 text-center text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.addon_quantity"))}</th><th class="px-3 py-2 text-right text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.addon_expires"))}</th></tr></thead><tbody class="divide-y divide-slate-700/50"><!--[-->`);
|
||
ssrRenderList(__props.garage.subscription.addons, (addon) => {
|
||
_push(`<tr class="bg-slate-900/20 hover:bg-slate-900/40 transition"><td class="px-3 py-2.5 text-slate-300">${ssrInterpolate(addonLabel(addon.type))}</td><td class="px-3 py-2.5 text-center"><span class="inline-flex items-center justify-center w-7 h-7 rounded-full bg-indigo-500/20 text-indigo-300 text-xs font-bold">${ssrInterpolate(addon.quantity)}</span></td><td class="px-3 py-2.5 text-right text-slate-500">`);
|
||
if (addon.expires_at || addon.valid_until) {
|
||
_push(`<span>${ssrInterpolate(formatDate(addon.expires_at || addon.valid_until))}</span>`);
|
||
} else {
|
||
_push(`<span class="italic">${ssrInterpolate(_ctx.$t("garages.indefinite"))}</span>`);
|
||
}
|
||
_push(`</td></tr>`);
|
||
});
|
||
_push(`<!--]--></tbody></table></div></div>`);
|
||
} else if (__props.garage.subscription) {
|
||
_push(`<div class="mt-4 border-t border-slate-700/50 pt-4"><p class="text-xs text-slate-500 uppercase tracking-wider mb-1">${ssrInterpolate(_ctx.$t("garages.active_addons"))}</p><div class="bg-slate-900/20 border border-slate-700/30 rounded-lg px-4 py-3 text-center"><p class="text-xs text-slate-500 italic">${ssrInterpolate(_ctx.$t("garages.no_active_addons"))}</p></div></div>`);
|
||
} else {
|
||
_push(`<div class="text-center py-4"><p class="text-sm text-slate-400">${ssrInterpolate(_ctx.$t("garages.details.no_subscription"))}</p></div>`);
|
||
}
|
||
_push(`</div></div><div class="bg-slate-800/50 border border-slate-700 rounded-xl overflow-hidden"><div class="px-6 py-4 border-b border-slate-700 flex items-center gap-3"><div class="p-2 rounded-lg bg-indigo-500/10 text-indigo-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path></svg></div><h3 class="text-base font-semibold text-white">${ssrInterpolate(_ctx.$t("garages.change_package"))}</h3></div><div class="px-6 py-5 space-y-5"><div><label class="block text-sm font-medium text-slate-300 mb-2">${ssrInterpolate(_ctx.$t("garages.select_package"))}</label><select class="w-full px-3 py-2.5 bg-slate-900 border border-slate-700 rounded-lg text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500/50 transition"><option value="" disabled${ssrIncludeBooleanAttr(Array.isArray(selectedTierId.value) ? ssrLooseContain(selectedTierId.value, "") : ssrLooseEqual(selectedTierId.value, "")) ? " selected" : ""}>${ssrInterpolate(_ctx.$t("garages.select_package_placeholder"))}</option><!--[-->`);
|
||
ssrRenderList(availableTiers.value, (tier) => {
|
||
_push(`<option${ssrRenderAttr("value", tier.id)}${ssrIncludeBooleanAttr(Array.isArray(selectedTierId.value) ? ssrLooseContain(selectedTierId.value, tier.id) : ssrLooseEqual(selectedTierId.value, tier.id)) ? " selected" : ""}>${ssrInterpolate(tier.name)} (Level ${ssrInterpolate(tier.tier_level)}) </option>`);
|
||
});
|
||
_push(`<!--]--></select></div><div><label class="block text-sm font-medium text-slate-300 mb-2">${ssrInterpolate(_ctx.$t("garages.custom_expiration"))} <span class="text-xs text-slate-500 ml-1">(${ssrInterpolate(_ctx.$t("garages.optional"))})</span></label><input${ssrRenderAttr("value", customExpiresAt.value)} type="date" class="w-full px-3 py-2.5 bg-slate-900 border border-slate-700 rounded-lg text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500/50 transition"><p class="text-xs text-slate-500 mt-1.5">${ssrInterpolate(_ctx.$t("garages.custom_expiration_hint"))}</p></div><div><label class="block text-sm font-medium text-slate-300 mb-3">${ssrInterpolate(_ctx.$t("garages.addons_title"))} <span class="text-xs text-slate-500 ml-1">(${ssrInterpolate(_ctx.$t("garages.optional"))})</span></label><div class="grid grid-cols-1 md:grid-cols-3 gap-3"><div class="bg-slate-900/30 border border-slate-700/50 rounded-lg p-3"><label class="block text-xs text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.addon_vehicles"))}</label><div class="flex items-center gap-2"><button class="w-8 h-8 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-300 flex items-center justify-center transition text-sm font-bold">−</button><input${ssrRenderAttr("value", extraVehicles.value)} type="number" min="0" max="999" class="w-full px-2 py-1.5 bg-slate-900 border border-slate-700 rounded-lg text-sm text-white text-center focus:outline-none focus:ring-2 focus:ring-indigo-500/50 transition [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"><button class="w-8 h-8 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-300 flex items-center justify-center transition text-sm font-bold">+</button></div><label class="block text-xs text-slate-500 mt-2 mb-1">${ssrInterpolate(_ctx.$t("garages.addon_vehicles_expiration"))}</label><input${ssrRenderAttr("value", addonDates.vehicles)} type="date" class="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500/50 transition"></div><div class="bg-slate-900/30 border border-slate-700/50 rounded-lg p-3"><label class="block text-xs text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.addon_branches"))}</label><div class="flex items-center gap-2"><button class="w-8 h-8 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-300 flex items-center justify-center transition text-sm font-bold">−</button><input${ssrRenderAttr("value", extraBranches.value)} type="number" min="0" max="999" class="w-full px-2 py-1.5 bg-slate-900 border border-slate-700 rounded-lg text-sm text-white text-center focus:outline-none focus:ring-2 focus:ring-indigo-500/50 transition [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"><button class="w-8 h-8 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-300 flex items-center justify-center transition text-sm font-bold">+</button></div><label class="block text-xs text-slate-500 mt-2 mb-1">${ssrInterpolate(_ctx.$t("garages.addon_branches_expiration"))}</label><input${ssrRenderAttr("value", addonDates.branches)} type="date" class="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500/50 transition"></div><div class="bg-slate-900/30 border border-slate-700/50 rounded-lg p-3"><label class="block text-xs text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.addon_users"))}</label><div class="flex items-center gap-2"><button class="w-8 h-8 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-300 flex items-center justify-center transition text-sm font-bold">−</button><input${ssrRenderAttr("value", extraUsers.value)} type="number" min="0" max="999" class="w-full px-2 py-1.5 bg-slate-900 border border-slate-700 rounded-lg text-sm text-white text-center focus:outline-none focus:ring-2 focus:ring-indigo-500/50 transition [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"><button class="w-8 h-8 rounded-lg bg-slate-800 hover:bg-slate-700 text-slate-300 flex items-center justify-center transition text-sm font-bold">+</button></div><label class="block text-xs text-slate-500 mt-2 mb-1">${ssrInterpolate(_ctx.$t("garages.addon_users_expiration"))}</label><input${ssrRenderAttr("value", addonDates.users)} type="date" class="w-full px-3 py-2 bg-slate-900 border border-slate-700 rounded-lg text-sm text-white focus:outline-none focus:ring-2 focus:ring-indigo-500/50 transition"></div></div><p class="text-xs text-slate-500 mt-3">${ssrInterpolate(_ctx.$t("garages.addon_expiration_hint"))}</p></div>`);
|
||
if (subscriptionSaveError.value) {
|
||
_push(`<div class="bg-red-500/10 border border-red-500/20 rounded-lg px-4 py-3"><p class="text-sm text-red-400">${ssrInterpolate(subscriptionSaveError.value)}</p></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`<div class="flex items-center justify-end gap-3 pt-2"><button${ssrIncludeBooleanAttr(subscriptionSaving.value || !selectedTierId.value && !addonsChanged.value) ? " disabled" : ""} class="${ssrRenderClass([subscriptionSaving.value ? "bg-indigo-600/50 text-indigo-200 cursor-wait" : "bg-indigo-600 text-white hover:bg-indigo-500", "px-5 py-2 text-sm font-medium rounded-lg transition disabled:opacity-50 disabled:cursor-not-allowed"])}">`);
|
||
if (subscriptionSaving.value) {
|
||
_push(`<span class="flex items-center gap-2"><svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg> ${ssrInterpolate(_ctx.$t("garages.saving"))}</span>`);
|
||
} else {
|
||
_push(`<span>${ssrInterpolate(_ctx.$t("garages.save"))}</span>`);
|
||
}
|
||
_push(`</button></div></div></div><div class="bg-slate-800/50 border border-slate-700 rounded-xl overflow-hidden"><div class="px-6 py-4 border-b border-slate-700 flex items-center gap-3"><div class="p-2 rounded-lg bg-cyan-500/10 text-cyan-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg></div><h3 class="text-base font-semibold text-white">${ssrInterpolate(_ctx.$t("garages.details.subscription_history"))}</h3></div><div class="px-6 py-5"><div class="overflow-x-auto"><table class="w-full text-sm"><thead><tr class="border-b border-slate-700"><th class="text-left px-4 py-3 text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.details.history_date"))}</th><th class="text-left px-4 py-3 text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.details.history_package"))}</th><th class="text-left px-4 py-3 text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.details.history_action"))}</th><th class="text-left px-4 py-3 text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.details.history_status"))}</th></tr></thead><tbody>`);
|
||
if (__props.garage?.subscription_history?.length) {
|
||
_push(`<!--[-->`);
|
||
ssrRenderList(__props.garage.subscription_history, (hist) => {
|
||
_push(`<tr class="border-b border-slate-700/50 last:border-b-0 hover:bg-slate-700/30 transition"><td class="px-4 py-3 text-sm text-slate-300">${ssrInterpolate(formatDate(hist.timestamp))}</td><td class="px-4 py-3 text-sm text-slate-300">${ssrInterpolate(hist.tier_name || "—")}</td><td class="px-4 py-3 text-sm text-slate-300 max-w-xs"><div class="space-y-1"><span class="text-xs text-slate-400 block">${ssrInterpolate(hist.action || "—")}</span>`);
|
||
if (formatChanges(hist)) {
|
||
_push(`<div class="text-xs text-slate-300 space-y-0.5"><!--[-->`);
|
||
ssrRenderList(formatChanges(hist), (line, li) => {
|
||
_push(`<div class="flex items-start gap-1"><span class="text-cyan-400 shrink-0">›</span><span>${ssrInterpolate(line)}</span></div>`);
|
||
});
|
||
_push(`<!--]--></div>`);
|
||
} else {
|
||
_push(`<span class="text-xs text-slate-500 italic">Nincs részletes adat</span>`);
|
||
}
|
||
_push(`</div></td><td class="px-4 py-3"><div class="flex flex-col gap-1"><span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-500/10 text-green-400"> Sikeres </span>`);
|
||
if (hist.admin_user_id) {
|
||
_push(`<span class="text-[10px] text-slate-500 text-center"> Admin #${ssrInterpolate(hist.admin_user_id)}</span>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</div></td></tr>`);
|
||
});
|
||
_push(`<!--]-->`);
|
||
} else {
|
||
_push(`<tr><td colspan="4" class="px-4 py-12 text-center"><div class="flex flex-col items-center gap-3"><svg class="w-10 h-10 text-slate-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg><p class="text-sm text-slate-400">${ssrInterpolate(_ctx.$t("garages.details.no_subscription_history"))}</p></div></td></tr>`);
|
||
}
|
||
_push(`</tbody></table></div></div></div></div>`);
|
||
};
|
||
}
|
||
});
|
||
const _sfc_setup$1 = _sfc_main$1.setup;
|
||
_sfc_main$1.setup = (props, ctx) => {
|
||
const ssrContext = useSSRContext();
|
||
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/garages/GarageSubscriptionTab.vue");
|
||
return _sfc_setup$1 ? _sfc_setup$1(props, ctx) : void 0;
|
||
};
|
||
const _sfc_main = /* @__PURE__ */ defineComponent({
|
||
__name: "index",
|
||
__ssrInlineRender: true,
|
||
setup(__props) {
|
||
const route = useRoute();
|
||
useRouter();
|
||
const auth = useAuthStore();
|
||
const orgId = route.params.id;
|
||
const loading = ref(true);
|
||
const error = ref(null);
|
||
const garage = ref(null);
|
||
const members = ref([]);
|
||
const activeTab = ref("general");
|
||
const fleetVehicles = ref([]);
|
||
const fleetLoading = ref(false);
|
||
const subscriptionTabRef = ref(null);
|
||
const showEditModal = ref(false);
|
||
const editModalTab = ref("basic");
|
||
const saving = ref(false);
|
||
const editForm = ref({
|
||
full_name: "",
|
||
name: "",
|
||
display_name: "",
|
||
email: "",
|
||
phone: "",
|
||
tax_number: "",
|
||
reg_number: "",
|
||
org_type: "",
|
||
address_zip: "",
|
||
address_city: "",
|
||
address_street_name: "",
|
||
address_street_type: "",
|
||
address_house_number: "",
|
||
contact_person_name: "",
|
||
contact_email: "",
|
||
contact_phone: "",
|
||
billing_zip: "",
|
||
billing_city: "",
|
||
billing_street_name: "",
|
||
billing_street_type: "",
|
||
billing_house_number: "",
|
||
notification_zip: "",
|
||
notification_city: "",
|
||
notification_street_name: "",
|
||
notification_street_type: "",
|
||
notification_house_number: ""
|
||
});
|
||
const showAddEmployeeModal = ref(false);
|
||
const newMemberEmail = ref("");
|
||
const newMemberRole = ref("member");
|
||
const addingMember = ref(false);
|
||
const showEditRoleModal = ref(false);
|
||
ref(null);
|
||
const editingRole = ref("member");
|
||
const savingRole = ref(false);
|
||
const showRemoveModal = ref(false);
|
||
const removingMember = ref(null);
|
||
const removing = ref(false);
|
||
const notification = ref({ show: false, type: "success", message: "" });
|
||
const tabs = [
|
||
{ key: "general", label: "garages.details.generalTab" },
|
||
{ key: "employees", label: "garages.details.employeesTab" },
|
||
{ key: "fleet", label: "garages.details.fleetTab" },
|
||
{ key: "subscription", label: "garages.details.subscriptionTab" },
|
||
{ key: "analytics", label: "garages.details.analyticsTab" }
|
||
];
|
||
const editModalTabs = [
|
||
{ key: "basic", label: "garages.details.editBasicTab" },
|
||
{ key: "contact", label: "garages.details.editContactTab" },
|
||
{ key: "addresses", label: "garages.details.editAddressTab" }
|
||
];
|
||
function hasOrgPermission(perm) {
|
||
if (auth.isAdmin) return true;
|
||
if (auth.user?.system_capabilities?.[perm]) return true;
|
||
if (auth.user?.org_capabilities?.[orgId]?.[perm]) return true;
|
||
return false;
|
||
}
|
||
const vehicleQuotaLimit = computed(() => {
|
||
if (!garage.value?.subscription?.asset_limit) return 5;
|
||
return garage.value.subscription.asset_limit;
|
||
});
|
||
const vehicleQuotaPercent = computed(() => {
|
||
const limit = vehicleQuotaLimit.value;
|
||
if (limit <= 0) return 0;
|
||
return Math.min(100, Math.round(fleetVehicles.value.length / limit * 100));
|
||
});
|
||
computed(() => {
|
||
const branches = garage.value?.branches?.length || 0;
|
||
const limit = garage.value?.subscription?.branch_limit;
|
||
if (!limit || limit <= 0) return 0;
|
||
return Math.min(100, Math.round(branches / limit * 100));
|
||
});
|
||
computed(() => {
|
||
const count = garage.value?.member_count || 0;
|
||
const limit = garage.value?.subscription?.user_limit;
|
||
if (!limit || limit <= 0) return 0;
|
||
return Math.min(100, Math.round(count / limit * 100));
|
||
});
|
||
const missingFields = computed(() => {
|
||
if (!garage.value) return [];
|
||
const missing = [];
|
||
const g = garage.value;
|
||
const isIndividual = g.org_type === "individual";
|
||
if (!isIndividual) {
|
||
if (!g.tax_number) missing.push({ key: "tax_number", label: "garages.details.missing_tax_number" });
|
||
}
|
||
if (!g.contact_email && !g.email) missing.push({ key: "contact_email", label: "garages.details.missing_contact_email" });
|
||
if (!g.contact_phone && !g.phone) missing.push({ key: "contact_phone", label: "garages.details.missing_contact_phone" });
|
||
if (!isIndividual) {
|
||
if (!g.billing_city || !g.billing_zip) missing.push({ key: "billing", label: "garages.details.missing_billing" });
|
||
}
|
||
return missing;
|
||
});
|
||
async function fetchDetails() {
|
||
loading.value = true;
|
||
error.value = null;
|
||
try {
|
||
const tokenCookie = useCookie("access_token");
|
||
const token = (tokenCookie.value || auth.token || "").trim();
|
||
const headers = {
|
||
"Authorization": `Bearer ${token}`,
|
||
"Content-Type": "application/json"
|
||
};
|
||
const res = await fetch(`/api/v1/admin/organizations/${orgId}/details`, { headers });
|
||
if (!res.ok) throw new Error(`Failed to fetch organization: ${res.status}`);
|
||
const data = await res.json();
|
||
garage.value = data;
|
||
members.value = data.members || [];
|
||
} catch (e) {
|
||
error.value = e.message || "Failed to load garage details";
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
}
|
||
async function fetchFleetVehicles() {
|
||
fleetLoading.value = true;
|
||
try {
|
||
const tokenCookie = useCookie("access_token");
|
||
const token = (tokenCookie.value || auth.token || "").trim();
|
||
const res = await fetch(`/api/v1/admin/organizations/${orgId}/vehicles`, {
|
||
headers: {
|
||
"Authorization": `Bearer ${token}`,
|
||
"Content-Type": "application/json"
|
||
}
|
||
});
|
||
if (!res.ok) throw new Error(`Failed to fetch fleet: ${res.status}`);
|
||
const data = await res.json();
|
||
fleetVehicles.value = data.vehicles || [];
|
||
} catch (e) {
|
||
console.error("Fleet fetch error:", e);
|
||
fleetVehicles.value = [];
|
||
} finally {
|
||
fleetLoading.value = false;
|
||
}
|
||
}
|
||
const cleanGarageName = computed(() => {
|
||
if (!garage.value) return "";
|
||
const raw = garage.value.display_name || garage.value.name || garage.value.full_name || "";
|
||
return raw.replace(/[\s-]*#\d+\s*$/g, "").trim() || "Garage #" + garage.value.id;
|
||
});
|
||
function garageDisplayName() {
|
||
if (!garage.value) return "";
|
||
return garage.value.name || garage.value.email || garage.value.full_name || "Garage #" + garage.value.id;
|
||
}
|
||
function getInitials(name) {
|
||
if (!name) return "?";
|
||
return name.split(" ").map((w) => w[0]).join("").toUpperCase().slice(0, 2);
|
||
}
|
||
function getInitialsColor(name) {
|
||
const colors = [
|
||
"bg-red-500",
|
||
"bg-yellow-500",
|
||
"bg-green-500",
|
||
"bg-blue-500",
|
||
"bg-indigo-500",
|
||
"bg-purple-500",
|
||
"bg-pink-500",
|
||
"bg-teal-500"
|
||
];
|
||
let hash = 0;
|
||
for (let i = 0; i < (name || "").length; i++) {
|
||
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
||
}
|
||
return colors[Math.abs(hash) % colors.length];
|
||
}
|
||
function statusLabel(status) {
|
||
const map = {
|
||
active: "Active",
|
||
inactive: "Inactive",
|
||
suspended: "Suspended",
|
||
pending: "Pending"
|
||
};
|
||
return map[status?.toLowerCase()] || status;
|
||
}
|
||
function statusBadgeClass(status) {
|
||
const map = {
|
||
active: "bg-green-100 text-green-800",
|
||
inactive: "bg-gray-100 text-gray-800",
|
||
suspended: "bg-red-100 text-red-800",
|
||
pending: "bg-yellow-100 text-yellow-800"
|
||
};
|
||
return map[status?.toLowerCase()] || "bg-gray-100 text-gray-800";
|
||
}
|
||
function statusDotClass(status) {
|
||
const map = {
|
||
active: "bg-green-400",
|
||
inactive: "bg-gray-400",
|
||
suspended: "bg-red-400",
|
||
pending: "bg-yellow-400"
|
||
};
|
||
return map[status?.toLowerCase()] || "bg-gray-400";
|
||
}
|
||
function memberFullName(member) {
|
||
if (!member) return "";
|
||
if (member.display_name) return member.display_name;
|
||
if (member.name) return member.name;
|
||
if (member.email) return member.email;
|
||
if (member.person) {
|
||
const first = member.person.first_name || "";
|
||
const last = member.person.last_name || "";
|
||
const full = `${last} ${first}`.trim();
|
||
if (full) return full;
|
||
if (member.person.email) return member.person.email;
|
||
}
|
||
if (member.user_id) return String(member.user_id);
|
||
return "Unknown";
|
||
}
|
||
function roleLabel(role) {
|
||
const map = {
|
||
admin: "Admin",
|
||
manager: "Manager",
|
||
member: "Member",
|
||
owner: "Owner"
|
||
};
|
||
return map[role?.toLowerCase()] || role || "Member";
|
||
}
|
||
function roleBadgeClass(role) {
|
||
const map = {
|
||
admin: "bg-purple-100 text-purple-800",
|
||
manager: "bg-blue-100 text-blue-800",
|
||
member: "bg-green-100 text-green-800",
|
||
owner: "bg-yellow-100 text-yellow-800"
|
||
};
|
||
return map[role?.toLowerCase()] || "bg-gray-100 text-gray-800";
|
||
}
|
||
function memberStatusLabel(status) {
|
||
const map = {
|
||
active: "Active",
|
||
invited: "Invited",
|
||
suspended: "Suspended",
|
||
inactive: "Inactive"
|
||
};
|
||
return map[status?.toLowerCase()] || status || "Unknown";
|
||
}
|
||
function memberStatusBadgeClass(status) {
|
||
const map = {
|
||
active: "bg-green-100 text-green-800",
|
||
invited: "bg-blue-100 text-blue-800",
|
||
suspended: "bg-red-100 text-red-800",
|
||
inactive: "bg-gray-100 text-gray-800"
|
||
};
|
||
return map[status?.toLowerCase()] || "bg-gray-100 text-gray-800";
|
||
}
|
||
function memberStatusDotClass(status) {
|
||
const map = {
|
||
active: "bg-green-400",
|
||
invited: "bg-blue-400",
|
||
suspended: "bg-red-400",
|
||
inactive: "bg-gray-400"
|
||
};
|
||
return map[status?.toLowerCase()] || "bg-gray-400";
|
||
}
|
||
watch(activeTab, (newTab) => {
|
||
if (newTab === "fleet" || newTab === "analytics" || newTab === "subscription") {
|
||
if (fleetVehicles.value.length === 0) {
|
||
fetchFleetVehicles();
|
||
}
|
||
}
|
||
if (newTab === "subscription") {
|
||
subscriptionTabRef.value?.fetchTiers();
|
||
}
|
||
});
|
||
return (_ctx, _push, _parent, _attrs) => {
|
||
const _component_GaragesGarageGeneralTab = _sfc_main$3;
|
||
const _component_GaragesGarageFleetTab = _sfc_main$2;
|
||
const _component_GaragesGarageSubscriptionTab = _sfc_main$1;
|
||
_push(`<div${ssrRenderAttrs(_attrs)}>`);
|
||
if (loading.value) {
|
||
_push(`<div class="flex items-center justify-center py-20"><div class="flex flex-col items-center gap-3"><svg class="w-8 h-8 text-indigo-400 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg><p class="text-slate-400 text-sm">${ssrInterpolate(_ctx.$t("garages.details.loading"))}</p></div></div>`);
|
||
} else if (error.value) {
|
||
_push(`<div class="flex flex-col items-center justify-center py-20 text-center"><svg class="w-12 h-12 text-red-500 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"></path></svg><p class="text-red-400 text-sm mb-2">${ssrInterpolate(error.value)}</p><button class="px-4 py-2 text-sm bg-indigo-600/20 text-indigo-300 hover:bg-indigo-600/30 rounded-lg transition">${ssrInterpolate(_ctx.$t("garages.details.retry"))}</button></div>`);
|
||
} else if (garage.value) {
|
||
_push(`<!--[-->`);
|
||
if (missingFields.value.length > 0) {
|
||
_push(`<div class="mb-6 p-4 bg-amber-500/10 border border-amber-500/30 rounded-xl"><div class="flex items-start gap-3"><div class="p-1.5 rounded-lg bg-amber-500/20 text-amber-400 flex-shrink-0"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"></path></svg></div><div class="flex-1 min-w-0"><div class="flex items-center justify-between"><p class="text-sm font-semibold text-amber-300">${ssrInterpolate(_ctx.$t("garages.details.missing_data_title"))}</p><span class="text-xs text-amber-400/70">${ssrInterpolate(_ctx.$t("garages.details.missing_data_count", { count: missingFields.value.length }))}</span></div><p class="text-xs text-amber-400/80 mt-1">${ssrInterpolate(garage.value.status !== "active" ? _ctx.$t("garages.details.missing_data_activation_required") : _ctx.$t("garages.details.missing_data_desc"))}</p><div class="flex flex-wrap gap-2 mt-3"><!--[-->`);
|
||
ssrRenderList(missingFields.value, (field) => {
|
||
_push(`<span class="inline-flex items-center gap-1 px-2.5 py-1 rounded-md text-xs font-medium bg-amber-500/10 text-amber-300"><svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg> ${ssrInterpolate(_ctx.$t(field.label))}</span>`);
|
||
});
|
||
_push(`<!--]--></div></div></div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`<div class="mb-8"><button class="inline-flex items-center gap-1.5 text-sm text-slate-400 hover:text-white transition mb-4"><svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path></svg> ${ssrInterpolate(_ctx.$t("garages.details.back"))}</button><div class="flex items-center justify-between"><div class="flex items-center gap-4"><div class="${ssrRenderClass([getInitialsColor(garageDisplayName()), "w-12 h-12 rounded-xl flex items-center justify-center text-lg font-bold text-white"])}">${ssrInterpolate(getInitials(garageDisplayName()))}</div><div><div class="flex items-center gap-3"><h1 class="text-2xl font-bold text-white">${ssrInterpolate(cleanGarageName.value)}</h1><span class="${ssrRenderClass([statusBadgeClass(garage.value.status), "inline-flex items-center px-3 py-1 rounded-full text-xs font-medium"])}"><span class="${ssrRenderClass([statusDotClass(garage.value.status), "w-1.5 h-1.5 rounded-full mr-1.5"])}"></span> ${ssrInterpolate(statusLabel(garage.value.status))}</span></div><p class="text-sm text-slate-400 mt-0.5">${ssrInterpolate(garage.value.full_name)} `);
|
||
if (garage.value.tax_number) {
|
||
_push(`<span class="ml-2 text-slate-500">· ${ssrInterpolate(_ctx.$t("garages.details.tax_number"))}: ${ssrInterpolate(garage.value.tax_number)}</span>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</p></div></div><div class="flex items-center gap-3">`);
|
||
if (hasOrgPermission("org:edit")) {
|
||
_push(`<button class="inline-flex items-center gap-1.5 px-4 py-2 text-sm font-medium bg-indigo-600/20 text-indigo-300 hover:bg-indigo-600/30 rounded-lg transition"><svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path></svg> ${ssrInterpolate(_ctx.$t("garages.details.edit_details"))}</button>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</div></div></div><div class="border-b border-slate-700 mb-6"><nav class="flex gap-6"><!--[-->`);
|
||
ssrRenderList(tabs, (tab) => {
|
||
_push(`<button class="${ssrRenderClass([activeTab.value === tab.key ? "text-indigo-400 border-indigo-400" : "text-slate-400 border-transparent hover:text-slate-300", "pb-3 text-sm font-medium transition border-b-2 -mb-px"])}">${ssrInterpolate(_ctx.$t(tab.label))}</button>`);
|
||
});
|
||
_push(`<!--]--></nav></div>`);
|
||
if (activeTab.value === "general") {
|
||
_push(ssrRenderComponent(_component_GaragesGarageGeneralTab, { garage: garage.value }, null, _parent));
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (activeTab.value === "employees") {
|
||
_push(`<div class="space-y-6"><div class="flex items-center justify-between"><div class="flex items-center gap-3"><div class="p-2 rounded-lg bg-cyan-500/10 text-cyan-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197m13.5-9a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z"></path></svg></div><div><h3 class="text-base font-semibold text-white">${ssrInterpolate(_ctx.$t("garages.employees.title"))}</h3><p class="text-xs text-slate-400 mt-0.5">${ssrInterpolate(_ctx.$t("garages.employees.total_count", { count: members.value.length }))}</p></div></div>`);
|
||
if (hasOrgPermission("org:manage-members")) {
|
||
_push(`<button class="inline-flex items-center gap-1.5 px-4 py-2 text-sm font-medium bg-emerald-600/20 text-emerald-300 hover:bg-emerald-600/30 rounded-lg transition"><svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18 9v3m0 0v3m0-3h3m-3 0h-3m-2-5a4 4 0 11-8 0 4 4 0 018 0zM3 20a6 6 0 0112 0v1H3v-1z"></path></svg> ${ssrInterpolate(_ctx.$t("garages.employees.add_employee"))}</button>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</div><div class="bg-slate-800/50 border border-slate-700 rounded-xl overflow-hidden"><div class="overflow-x-auto"><table class="w-full text-sm"><thead><tr class="border-b border-slate-700"><th class="text-left px-4 py-3 text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.employees.name"))}</th><th class="text-left px-4 py-3 text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.employees.email_phone"))}</th><th class="text-left px-4 py-3 text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.employees.role"))}</th><th class="text-left px-4 py-3 text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.employees.status"))}</th><th class="text-right px-4 py-3 text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.employees.actions"))}</th></tr></thead><tbody><!--[-->`);
|
||
ssrRenderList(members.value, (member) => {
|
||
_push(`<tr class="border-b border-slate-700/50 last:border-b-0 hover:bg-slate-700/30 transition"><td class="px-4 py-3"><div class="flex items-center gap-3"><div class="${ssrRenderClass([getInitialsColor(memberFullName(member)), "w-8 h-8 rounded-lg flex items-center justify-center text-xs font-bold text-white flex-shrink-0"])}">${ssrInterpolate(getInitials(memberFullName(member)))}</div><div><p class="text-sm font-medium text-white">${ssrInterpolate(memberFullName(member))}</p><p class="text-xs text-slate-500">ID: ${ssrInterpolate(member.user_id || member.id)}</p><div class="flex gap-3 mt-0.5 text-xs text-slate-500 font-mono"><span>User_id: <span class="text-slate-400">${ssrInterpolate(member.user_id || "N/A")}</span></span><span>Person_id: <span class="text-slate-400">${ssrInterpolate(member.person?.id || "N/A")}</span></span></div></div></div></td><td class="px-4 py-3"><div class="space-y-0.5">`);
|
||
if (member.person?.email) {
|
||
_push(`<p class="text-sm text-slate-300">${ssrInterpolate(member.person.email)}</p>`);
|
||
} else {
|
||
_push(`<p class="text-sm text-slate-500 italic">—</p>`);
|
||
}
|
||
if (member.person?.phone) {
|
||
_push(`<p class="text-xs text-slate-400">${ssrInterpolate(member.person.phone)}</p>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</div></td><td class="px-4 py-3"><span class="${ssrRenderClass([roleBadgeClass(member.role), "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium"])}">${ssrInterpolate(roleLabel(member.role))}</span></td><td class="px-4 py-3"><span class="${ssrRenderClass([memberStatusBadgeClass(member.status), "inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium"])}"><span class="${ssrRenderClass([memberStatusDotClass(member.status), "w-1.5 h-1.5 rounded-full"])}"></span> ${ssrInterpolate(memberStatusLabel(member.status))}</span></td><td class="px-4 py-3 text-right"><div class="flex items-center justify-end gap-2">`);
|
||
if (hasOrgPermission("org:manage-members")) {
|
||
_push(`<button class="inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-indigo-300 bg-indigo-500/10 hover:bg-indigo-500/20 rounded-lg transition"><svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path></svg> ${ssrInterpolate(_ctx.$t("garages.employees.edit_role"))}</button>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (hasOrgPermission("org:manage-members")) {
|
||
_push(`<button class="inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium text-red-300 bg-red-500/10 hover:bg-red-500/20 rounded-lg transition"><svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg> ${ssrInterpolate(_ctx.$t("garages.employees.remove"))}</button>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</div></td></tr>`);
|
||
});
|
||
_push(`<!--]-->`);
|
||
if (members.value.length === 0) {
|
||
_push(`<tr><td colspan="5" class="px-4 py-12 text-center"><svg class="w-10 h-10 text-slate-600 mx-auto mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"></path></svg><p class="text-sm text-slate-400">${ssrInterpolate(_ctx.$t("garages.employees.no_employees"))}</p></td></tr>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</tbody></table></div></div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (activeTab.value === "fleet") {
|
||
_push(ssrRenderComponent(_component_GaragesGarageFleetTab, {
|
||
garage: garage.value,
|
||
"org-id": unref(orgId),
|
||
"fleet-vehicles": fleetVehicles.value,
|
||
"fleet-loading": fleetLoading.value
|
||
}, null, _parent));
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (activeTab.value === "subscription") {
|
||
_push(ssrRenderComponent(_component_GaragesGarageSubscriptionTab, {
|
||
ref_key: "subscriptionTabRef",
|
||
ref: subscriptionTabRef,
|
||
garage: garage.value,
|
||
"fleet-vehicles": fleetVehicles.value,
|
||
onRefresh: fetchDetails
|
||
}, null, _parent));
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (activeTab.value === "analytics") {
|
||
_push(`<div class="space-y-6"><div class="grid grid-cols-1 md:grid-cols-3 gap-4"><div class="bg-slate-800/50 border border-slate-700 rounded-xl p-5"><div class="flex items-center gap-3 mb-3"><div class="p-2 rounded-lg bg-emerald-500/10 text-emerald-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"></path></svg></div><span class="text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.analytics.ltv"))}</span></div><p class="text-2xl font-bold text-white">150 000 Ft</p><p class="text-xs text-emerald-400 mt-1 flex items-center gap-1"><svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 10l7-7m0 0l7 7m-7-7v18"></path></svg> +12% ezen a hónapon </p></div><div class="bg-slate-800/50 border border-slate-700 rounded-xl p-5"><div class="flex items-center gap-3 mb-3"><div class="p-2 rounded-lg bg-blue-500/10 text-blue-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg></div><span class="text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.analytics.mrr"))}</span></div><p class="text-2xl font-bold text-white">15 000 Ft</p><p class="text-xs text-slate-400 mt-1">${ssrInterpolate(_ctx.$t("garages.analytics.monthly_recurring"))}</p></div><div class="bg-slate-800/50 border border-slate-700 rounded-xl p-5"><div class="flex items-center gap-3 mb-3"><div class="p-2 rounded-lg bg-amber-500/10 text-amber-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 14l6-6m-5.5.5h.01m4.99 5h.01M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16l3.5-2 3.5 2 3.5-2 3.5 2zM10 8.5a.5.5 0 11-1 0 .5.5 0 011 0zm5 5a.5.5 0 11-1 0 .5.5 0 011 0z"></path></svg></div><span class="text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.analytics.outstanding"))}</span></div><p class="text-2xl font-bold text-white">0 Ft</p><p class="text-xs text-emerald-400 mt-1 flex items-center gap-1"><svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg> ${ssrInterpolate(_ctx.$t("garages.analytics.all_settled"))}</p></div></div><div class="grid grid-cols-1 md:grid-cols-3 gap-4"><div class="bg-slate-800/50 border border-slate-700 rounded-xl p-5"><div class="flex items-center gap-3 mb-3"><div class="p-2 rounded-lg bg-yellow-500/10 text-yellow-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"></path></svg></div><span class="text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.analytics.earned_credits"))}</span></div><p class="text-2xl font-bold text-yellow-300">450 XP</p><p class="text-xs text-slate-400 mt-1">${ssrInterpolate(_ctx.$t("garages.analytics.contribution_xp"))}</p></div><div class="bg-slate-800/50 border border-slate-700 rounded-xl p-5"><div class="flex items-center gap-3 mb-3"><div class="p-2 rounded-lg bg-purple-500/10 text-purple-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18 9v3m0 0v3m0-3h3m-3 0h-3m-2-5a4 4 0 11-8 0 4 4 0 018 0zM3 20a6 6 0 0112 0v1H3v-1z"></path></svg></div><span class="text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.analytics.invited_companies"))}</span></div><p class="text-2xl font-bold text-white">12</p><p class="text-xs text-slate-400 mt-1">${ssrInterpolate(_ctx.$t("garages.analytics.companies_joined"))}</p></div><div class="bg-slate-800/50 border border-slate-700 rounded-xl p-5"><div class="flex items-center gap-3 mb-3"><div class="p-2 rounded-lg bg-cyan-500/10 text-cyan-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"></path></svg></div><span class="text-xs font-medium text-slate-400 uppercase tracking-wider">${ssrInterpolate(_ctx.$t("garages.analytics.validated_garages"))}</span></div><p class="text-2xl font-bold text-white">8</p><p class="text-xs text-slate-400 mt-1">${ssrInterpolate(_ctx.$t("garages.analytics.garages_confirmed"))}</p></div></div><div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div class="bg-slate-800/50 border border-slate-700 rounded-xl p-5"><div class="flex items-center gap-3 mb-4"><div class="p-2 rounded-lg bg-indigo-500/10 text-indigo-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path></svg></div><h3 class="text-sm font-semibold text-white">${ssrInterpolate(_ctx.$t("garages.analytics.utilization"))}</h3></div><div class="mb-4"><div class="flex items-center justify-between mb-1.5"><span class="text-xs text-slate-400">${ssrInterpolate(_ctx.$t("garages.analytics.vehicle_quota"))}</span><span class="text-xs text-slate-500">${ssrInterpolate(fleetVehicles.value.length)} / ${ssrInterpolate(vehicleQuotaLimit.value)}</span></div><div class="w-full h-2 bg-slate-700 rounded-full overflow-hidden"><div class="${ssrRenderClass([vehicleQuotaPercent.value >= 90 ? "bg-red-500" : vehicleQuotaPercent.value >= 70 ? "bg-amber-500" : "bg-blue-500", "h-full rounded-full transition-all duration-500"])}" style="${ssrRenderStyle({ width: vehicleQuotaPercent.value + "%" })}"></div></div><p class="text-xs text-slate-500 mt-1">${ssrInterpolate(vehicleQuotaPercent.value)}% ${ssrInterpolate(_ctx.$t("garages.analytics.utilized"))}</p></div></div><div class="bg-slate-800/50 border border-slate-700 rounded-xl p-5"><div class="flex items-center gap-3 mb-4"><div class="p-2 rounded-lg bg-pink-500/10 text-pink-400"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 3.055A9.001 9.001 0 1020.945 13H11V3.055z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.488 9H15V3.512A9.025 9.025 0 0120.488 9z"></path></svg></div><h3 class="text-sm font-semibold text-white">${ssrInterpolate(_ctx.$t("garages.analytics.marketplace_engagement"))}</h3></div><div class="flex items-center justify-between py-2 border-b border-slate-700/50"><span class="text-xs text-slate-400">${ssrInterpolate(_ctx.$t("garages.analytics.avg_rating"))}</span><div class="flex items-center gap-1"><svg class="w-4 h-4 text-yellow-400" fill="currentColor" viewBox="0 0 20 20"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path></svg><span class="text-sm font-medium text-white">4.8</span></div></div><div class="flex items-center justify-between py-2 border-b border-slate-700/50"><span class="text-xs text-slate-400">${ssrInterpolate(_ctx.$t("garages.analytics.total_reviews"))}</span><span class="text-sm font-medium text-white">124</span></div><div class="flex items-center justify-between py-2 border-b border-slate-700/50"><span class="text-xs text-slate-400">${ssrInterpolate(_ctx.$t("garages.analytics.service_requests"))}</span><span class="text-sm font-medium text-white">47</span></div><div class="flex items-center justify-between py-2"><span class="text-xs text-slate-400">${ssrInterpolate(_ctx.$t("garages.analytics.response_rate"))}</span><span class="text-sm font-medium text-emerald-400">92%</span></div></div></div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (showEditModal.value) {
|
||
_push(`<div class="fixed inset-0 z-50 flex items-center justify-center p-4"><div class="absolute inset-0 bg-black/60 backdrop-blur-sm"></div><div class="relative w-full max-w-2xl bg-slate-800 border border-slate-700 rounded-2xl shadow-2xl max-h-[90vh] overflow-hidden flex flex-col"><div class="px-6 py-4 border-b border-slate-700 flex items-center justify-between flex-shrink-0"><h3 class="text-lg font-semibold text-white">${ssrInterpolate(_ctx.$t("garages.details.edit_details"))}</h3><button class="p-1.5 rounded-lg text-slate-400 hover:text-white hover:bg-slate-700 transition"><svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg></button></div><div class="px-6 pt-4 border-b border-slate-700 flex-shrink-0"><nav class="flex gap-4"><!--[-->`);
|
||
ssrRenderList(editModalTabs, (tab) => {
|
||
_push(`<button class="${ssrRenderClass([editModalTab.value === tab.key ? "text-indigo-400 border-indigo-400" : "text-slate-400 border-transparent hover:text-slate-300", "pb-3 text-sm font-medium transition border-b-2 -mb-px"])}">${ssrInterpolate(_ctx.$t(tab.label))}</button>`);
|
||
});
|
||
_push(`<!--]--></nav></div><div class="flex-1 overflow-y-auto p-6 space-y-6">`);
|
||
if (editModalTab.value === "basic") {
|
||
_push(`<div class="space-y-5"><div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.company_name"))}</label><input${ssrRenderAttr("value", editForm.value.full_name)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.display_name"))}</label><input${ssrRenderAttr("value", editForm.value.display_name)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div></div><div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.tax_number"))}</label><input${ssrRenderAttr("value", editForm.value.tax_number)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.reg_number"))}</label><input${ssrRenderAttr("value", editForm.value.reg_number)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div></div><div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.zip"))}</label><input${ssrRenderAttr("value", editForm.value.address_zip)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.city"))}</label><input${ssrRenderAttr("value", editForm.value.address_city)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div></div><div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.street_name"))}</label><input${ssrRenderAttr("value", editForm.value.address_street_name)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.street_type"))}</label><input${ssrRenderAttr("value", editForm.value.address_street_type)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div></div><div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.house_number"))}</label><input${ssrRenderAttr("value", editForm.value.address_house_number)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div></div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (editModalTab.value === "contact") {
|
||
_push(`<div class="space-y-5"><div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.contact_person"))}</label><input${ssrRenderAttr("value", editForm.value.contact_person_name)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.contact_email"))}</label><input${ssrRenderAttr("value", editForm.value.contact_email)} type="email" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div></div><div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.contact_phone"))}</label><input${ssrRenderAttr("value", editForm.value.contact_phone)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div></div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (editModalTab.value === "addresses") {
|
||
_push(`<div class="space-y-8"><div><h4 class="text-sm font-semibold text-white mb-3">${ssrInterpolate(_ctx.$t("garages.details.billing_address"))}</h4><div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.zip"))}</label><input${ssrRenderAttr("value", editForm.value.billing_zip)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.city"))}</label><input${ssrRenderAttr("value", editForm.value.billing_city)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div></div><div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4"><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.street_name"))}</label><input${ssrRenderAttr("value", editForm.value.billing_street_name)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.street_type"))}</label><input${ssrRenderAttr("value", editForm.value.billing_street_type)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div></div><div class="mt-4"><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.house_number"))}</label><input${ssrRenderAttr("value", editForm.value.billing_house_number)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div></div><div><h4 class="text-sm font-semibold text-white mb-3">${ssrInterpolate(_ctx.$t("garages.details.notification_address"))}</h4><div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.zip"))}</label><input${ssrRenderAttr("value", editForm.value.notification_zip)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.city"))}</label><input${ssrRenderAttr("value", editForm.value.notification_city)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div></div><div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4"><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.street_name"))}</label><input${ssrRenderAttr("value", editForm.value.notification_street_name)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.street_type"))}</label><input${ssrRenderAttr("value", editForm.value.notification_street_type)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div></div><div class="mt-4"><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.details.house_number"))}</label><input${ssrRenderAttr("value", editForm.value.notification_house_number)} type="text" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"></div></div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</div><div class="px-6 py-4 border-t border-slate-700 flex items-center justify-end gap-3 flex-shrink-0"><button class="px-4 py-2 text-sm font-medium text-slate-300 hover:text-white bg-slate-700/50 hover:bg-slate-700 rounded-lg transition">${ssrInterpolate(_ctx.$t("garages.details.cancel"))}</button><button${ssrIncludeBooleanAttr(saving.value) ? " disabled" : ""} class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-500 rounded-lg transition disabled:opacity-50 disabled:cursor-not-allowed">`);
|
||
if (saving.value) {
|
||
_push(`<svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(` ${ssrInterpolate(saving.value ? _ctx.$t("garages.details.saving") : _ctx.$t("garages.details.save"))}</button></div></div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (showAddEmployeeModal.value) {
|
||
_push(`<div class="fixed inset-0 z-50 flex items-center justify-center p-4"><div class="absolute inset-0 bg-black/60 backdrop-blur-sm"></div><div class="relative w-full max-w-md bg-slate-800 border border-slate-700 rounded-2xl shadow-2xl p-6"><h3 class="text-lg font-semibold text-white mb-4">${ssrInterpolate(_ctx.$t("garages.employees.add_employee"))}</h3><div class="space-y-4"><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.employees.email"))}</label><input${ssrRenderAttr("value", newMemberEmail.value)} type="email" class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"${ssrRenderAttr("placeholder", _ctx.$t("garages.employees.email_placeholder"))}></div><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.employees.role"))}</label><select class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"><option value="member"${ssrIncludeBooleanAttr(Array.isArray(newMemberRole.value) ? ssrLooseContain(newMemberRole.value, "member") : ssrLooseEqual(newMemberRole.value, "member")) ? " selected" : ""}>${ssrInterpolate(_ctx.$t("garages.roles.member"))}</option><option value="manager"${ssrIncludeBooleanAttr(Array.isArray(newMemberRole.value) ? ssrLooseContain(newMemberRole.value, "manager") : ssrLooseEqual(newMemberRole.value, "manager")) ? " selected" : ""}>${ssrInterpolate(_ctx.$t("garages.roles.manager"))}</option><option value="admin"${ssrIncludeBooleanAttr(Array.isArray(newMemberRole.value) ? ssrLooseContain(newMemberRole.value, "admin") : ssrLooseEqual(newMemberRole.value, "admin")) ? " selected" : ""}>${ssrInterpolate(_ctx.$t("garages.roles.admin"))}</option></select></div></div><div class="flex justify-end gap-3 mt-6"><button class="px-4 py-2 text-sm font-medium text-slate-300 hover:text-white bg-slate-700/50 hover:bg-slate-700 rounded-lg transition">${ssrInterpolate(_ctx.$t("garages.employees.cancel"))}</button><button${ssrIncludeBooleanAttr(addingMember.value || !newMemberEmail.value) ? " disabled" : ""} class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-emerald-600 hover:bg-emerald-500 rounded-lg transition disabled:opacity-50 disabled:cursor-not-allowed">`);
|
||
if (addingMember.value) {
|
||
_push(`<svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(` ${ssrInterpolate(addingMember.value ? _ctx.$t("garages.employees.adding") : _ctx.$t("garages.employees.add"))}</button></div></div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (showEditRoleModal.value) {
|
||
_push(`<div class="fixed inset-0 z-50 flex items-center justify-center p-4"><div class="absolute inset-0 bg-black/60 backdrop-blur-sm"></div><div class="relative w-full max-w-md bg-slate-800 border border-slate-700 rounded-2xl shadow-2xl p-6"><h3 class="text-lg font-semibold text-white mb-4">${ssrInterpolate(_ctx.$t("garages.employees.edit_role"))}</h3><div><label class="block text-xs font-medium text-slate-400 mb-1.5">${ssrInterpolate(_ctx.$t("garages.employees.role"))}</label><select class="w-full px-3 py-2 text-sm bg-slate-700/50 border border-slate-600 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500"><option value="member"${ssrIncludeBooleanAttr(Array.isArray(editingRole.value) ? ssrLooseContain(editingRole.value, "member") : ssrLooseEqual(editingRole.value, "member")) ? " selected" : ""}>${ssrInterpolate(_ctx.$t("garages.roles.member"))}</option><option value="manager"${ssrIncludeBooleanAttr(Array.isArray(editingRole.value) ? ssrLooseContain(editingRole.value, "manager") : ssrLooseEqual(editingRole.value, "manager")) ? " selected" : ""}>${ssrInterpolate(_ctx.$t("garages.roles.manager"))}</option><option value="admin"${ssrIncludeBooleanAttr(Array.isArray(editingRole.value) ? ssrLooseContain(editingRole.value, "admin") : ssrLooseEqual(editingRole.value, "admin")) ? " selected" : ""}>${ssrInterpolate(_ctx.$t("garages.roles.admin"))}</option></select></div><div class="flex justify-end gap-3 mt-6"><button class="px-4 py-2 text-sm font-medium text-slate-300 hover:text-white bg-slate-700/50 hover:bg-slate-700 rounded-lg transition">${ssrInterpolate(_ctx.$t("garages.employees.cancel"))}</button><button${ssrIncludeBooleanAttr(savingRole.value) ? " disabled" : ""} class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-500 rounded-lg transition disabled:opacity-50 disabled:cursor-not-allowed">`);
|
||
if (savingRole.value) {
|
||
_push(`<svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(` ${ssrInterpolate(savingRole.value ? _ctx.$t("garages.employees.saving") : _ctx.$t("garages.employees.save"))}</button></div></div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (showRemoveModal.value) {
|
||
_push(`<div class="fixed inset-0 z-50 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true"><div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"><div class="fixed inset-0 bg-black/60 backdrop-blur-sm transition-opacity"></div><span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true"></span><div class="inline-block align-bottom bg-slate-800 rounded-2xl px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl border border-slate-700 transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full sm:p-6"><div class="sm:flex sm:items-start"><div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-500/20 sm:mx-0 sm:h-10 sm:w-10"><svg class="h-6 w-6 text-red-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"></path></svg></div><div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"><h3 class="text-lg leading-6 font-medium text-white">${ssrInterpolate(_ctx.$t("garages.employees.removeTitle"))}</h3><div class="mt-2"><p class="text-sm text-slate-400">${ssrInterpolate(_ctx.$t("garages.employees.removeConfirm", { name: memberFullName(removingMember.value) }))}</p></div></div></div><div class="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse gap-2"><button${ssrIncludeBooleanAttr(removing.value) ? " disabled" : ""} type="button" class="w-full inline-flex justify-center rounded-xl border border-transparent shadow-sm px-4 py-2.5 bg-red-600 text-base font-medium text-white hover:bg-red-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:w-auto sm:text-sm disabled:opacity-50 disabled:cursor-not-allowed transition">`);
|
||
if (removing.value) {
|
||
_push(`<svg class="w-4 h-4 animate-spin mr-2" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(` ${ssrInterpolate(removing.value ? _ctx.$t("garages.employees.removing") : _ctx.$t("garages.employees.remove"))}</button><button type="button" class="mt-3 w-full inline-flex justify-center rounded-xl border border-slate-600 shadow-sm px-4 py-2.5 bg-slate-700/50 text-base font-medium text-slate-300 hover:bg-slate-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:w-auto sm:text-sm transition">${ssrInterpolate(_ctx.$t("garages.employees.cancel"))}</button></div></div></div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (notification.value.show) {
|
||
_push(`<div class="fixed top-4 right-4 z-[100] max-w-sm w-full bg-slate-800 border border-slate-700 shadow-lg rounded-xl pointer-events-auto overflow-hidden"><div class="p-4"><div class="flex items-start"><div class="flex-shrink-0">`);
|
||
if (notification.value.type === "success") {
|
||
_push(`<svg class="h-6 w-6 text-green-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
if (notification.value.type === "error") {
|
||
_push(`<svg class="h-6 w-6 text-red-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"></path></svg>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</div><div class="ml-3 w-0 flex-1 pt-0.5"><p class="text-sm font-medium text-white">${ssrInterpolate(notification.value.message)}</p></div><div class="ml-4 flex-shrink-0 flex"><button class="bg-slate-700/50 rounded-md inline-flex text-slate-400 hover:text-slate-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"><span class="sr-only">Close</span><svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"></path></svg></button></div></div></div></div>`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`<!--]-->`);
|
||
} else {
|
||
_push(`<!---->`);
|
||
}
|
||
_push(`</div>`);
|
||
};
|
||
}
|
||
});
|
||
const _sfc_setup = _sfc_main.setup;
|
||
_sfc_main.setup = (props, ctx) => {
|
||
const ssrContext = useSSRContext();
|
||
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("pages/garages/[id]/index.vue");
|
||
return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
|
||
};
|
||
export {
|
||
_sfc_main as default
|
||
};
|
||
//# sourceMappingURL=index-CKl-ge5n.js.map
|