1import { b as H, d as W } from "./index-CDyB1Hog.js"; 2import { C as $, a as C, L as q, P as G, e as J, p as K, b as A, c as O, B as Q, d as X, A as j, D as z } from "./index-D1Lny374.js"; 3import { g, a as E } from "./functions-DLrKIvnr.js"; 4import { j as D, o as f, c as b, a, e as m, u as s, t as v, g as h, y as Y, G as te, J as se, f as k, i as I, w as ae, d as B, E as N, b as V, l as re, z as oe, n as ie, s as ne, F as le } from "./app-yg_pP4S4.js"; 5import { r as Z } from "./StarIcon-Vd8SoMYy.js"; 6import { C as S } from "./utils-BpM2ZXfl.js"; 7import { _ as de } from "./ExportCsvButton-Du7MQ9Q7.js"; 8import { S as U } from "./SelectMultipleUsers-JlfGTheN.js"; 9import { _ as F } from "./StarsRating-sNZpPsOi.js"; 10import { _ as ce } from "./Table-D1P44re1.js"; 11import { r as P } from "./routes-DxhWgn2H.js"; 12import { _ as ue } from "./TimesheetReportFilters-F4CkM7Rm.js"; 13import { _ as me } from "./DashboardLayout-CXf_hhYT.js"; 14import { aM as pe } from "./XMarkIcon-C7ztHuKP.js"; 15import "./BaseButton-DP1PFEmO.js"; 16import "./LoaderIcon-BfI_LFZK.js"; 17import "./_plugin-vue_export-helper-DlAUqK2U.js"; 18import "./UserAvatar-B3-R1wxh.js"; 19import "./LiveChat-BEmWJs6j.js"; 20import "./ApplicationLogo-D4QkytOJ.js"; 21import "./popover-DTQdCRwt.js"; 22import "./consts-7Qk9bpse.js"; 23import "./form-BcDj1t5Y.js"; 24import "./BaseInput-DrEncIoW.js"; 25import "./ModalConfirmation-BptK8hn4.js"; 26import "./index-BF2h0ubX.js"; 27import "./CheckIcon-Bb6ppPFl.js"; 28import "./modelWrapper-D0DowOi8.js"; 29import "./TablePagination-CoQin-sh.js"; 30import "./listbox-BVei8WBz.js"; 31import "./use-text-value-9Z6g_4jd.js"; 32import "./ChevronUpDownIcon-D7fhXTZr.js"; 33import "./CheckIcon-CfE0icDF.js"; 34import "./ChevronRightIcon-f6ucdGu7.js"; 35import "./ArrowUpIcon-c4MStV6E.js"; 36import "./BaseListbox-BuI0rG6W.js"; 37import "./ChevronDownIcon-DvXuQ_5B.js"; 38import "./DateRangeSelector-DhOC_DFJ.js"; 39import "./PopoverTrigger-h40MnL1t.js"; 40import "./floating-ui.dom-CTpg9ddO.js"; 41import "./ChevronLeftIcon-DQwM_A8C.js"; 42import "./useEdgeFade-BW6BLoUc.js"; 43import "./UsersIcon-X_sH9UX4.js"; 44import "./UserGroupIcon-C4-PAwZM.js"; 45import "./Squares2X2Icon-0NsLubu9.js"; 46import "./TagIcon-BCQ4IKXC.js"; 47import "./BanknotesIcon-BGujvVnW.js"; 48import "./BaseModal-lnT_D81c.js"; 49import "./EyeIcon-C30yl1ND.js"; 50import "./HomeIcon-B7IW8yDA.js"; 51import "./MinusIcon-C5ZUuSoW.js"; 52import "./menu-DpWDC0YJ.js"; 53import "./use-tree-walker-DC0osvAV.js"; 54import "./vue-transitions-DxcThSkT.js"; 55import "./ClockIcon-DWc8x_ii.js"; 56const _e = { key: 0, class: "p-8 sm:p-20" }, ge = { class: "m-auto text-center" }, ve = { class: "mb-3 text-xl font-semibold text-gray-900" }, he = { key: 1, class: "rounded-md border bg-white shadow" }, fe = { class: "p-4 text-base font-semibold text-black" }, be = { class: "p-2" }, we = { __name: "AvgRatingBarChart", props: { reviews: { type: Object, required: true }, startDate: { type: [String, Date], required: false }, endDate: { type: [String, Date], required: false } }, setup(d) { 57 const { t: o } = D(), p = H(W).smaller("sm"); 58 $.register(C, q, G, J, K, A, O, Q); 59 const r = d, i = h(() => { 60 const l = g(r.startDate ?? g().subtract(1, "month")), t = g(r.endDate ?? g()); 61 let c = "day"; 62 return t.diff(l, "day") >= 35 && (c = "week"), t.diff(l, "day") >= 180 && (c = "month"), c; 63 }), u = (l) => { 64 const t = g(l.created_at).tz("UTC"); 65 return i.value === "day" ? t.format("YYYY-MM-DD") : i.value === "week" ? t.week() : t.format("MMM"); 66 }, e = h(() => { 67 const l = _.groupBy(_.cloneDeep(r.reviews), u); 68 return Y.mapValues(l, (t) => t.filter((c) => c.id).map((c) => c.rating).reduce((c, M) => c + M, 0) / t.length); 69 }), w = h(() => _.sum(Object.values(e.value))), x = h(() => w.value === 0), n = (l) => l.sort((t, c) => i.value === "day" ? g(t).isBefore(g(c)) ? -1 : 1 : i.value === "week" ? t - c : g(`01 ${t}`).isBefore(g(`01 ${c}`)) ? -1 : 1), y = (l) => l.map((t) => i.value === "day" ? (t = g(t), t.format("DD MMM")) : i.value === "week" ? o("Week {week}", { week: t }) : t), R = h(() => { 70 const l = e.value, t = n(Object.keys(l)), c = y(t), M = t.map((T) => l[T]); 71 return { labels: c, datasets: [{ label: o("Average"), backgroundColor: "rgba(79,70,229,1)", data: M, borderRadius: 8 }] }; 72 }), L = h(() => ({ responsive: true, maintainAspectRatio: false, plugins: { tooltip: { mode: "index", intersect: false }, legend: { display: false } }, scales: { y: { ticks: { color: "#A3A3A3" }, grid: { display: false }, stacked: true }, x: { ticks: { color: "#A3A3A3", ...p.value ? { maxTicksLimit: 5, maxRotation: 0, minRotation: 0 } : { maxTicksLimit: 10, maxRotation: 45, minRotation: 45 } }, grid: { display: false }, stacked: true } } })); 73 return (l, t) => x.value ? (f(), b("div", _e, [a("div", ge, [m(s(Z), { class: "mx-auto mb-5 h-12 w-12 stroke-2 text-gray-400" }), a("h3", ve, v(s(o)("No reviews yet")), 1)])])) : (f(), b("div", he, [a("div", fe, v(s(o)("Average rating")), 1
73), a("div", be, [m(s(X), { data: R.value, options: L.value, style: { height: "307px", width: "100%" } }, null, 8, ["data", "options"])])])); 74} }, ye = { class: "rounded-md bg-white p-6 shadow" }, xe = { class: "mb-6 font-semibold leading-tight text-gray-900" }, ke = { __name: "RatingDoughnutChart", props: { reviews: { type: Array, required: true } }, setup(d) { 75 $.register(j, A, O, q, C); 76 const o = d, { t: p } = D(), r = h(() => { 77 const u = _.chain(o.reviews).groupBy((n) => n.rating).mapValues((n) => n.length).value(), e = Object.keys(u), w = e.map((n) => p("{rating} star", { rating: n })), x = e.map((n) => u[n]); 78 return { labels: w, datasets: [{ label: p("Count"), data: x, backgroundColor: Object.values(S) }] }; 79 }), i = h(() => ({ responsive: true, maintainAspectRatio: false, plugins: { legend: { display: true, position: "bottom" } } })); 80 return (u, e) => (f(), b("div", ye, [a("div", xe, v(s(p)("Rating")), 1), a("div", null, [m(s(z), { data: r.value, options: i.value, style: { height: "324px", width: "100%" } }, null, 8, ["data", "options"])])])); 81} }, De = { class: "rounded-md bg-white p-6 shadow" }, Re = { class: "mb-6 font-semibold leading-tight text-gray-900" }, $e = { __name: "RatingOrganizationChart", props: { reviews: { type: Array, required: true } }, setup(d) { 82 $.register(j, A, O, q, C); 83 const o = d, { t: p } = D(), r = h(() => { 84 const u = _.chain(o.reviews).groupBy((n) => n.request.organization.name).mapValues((n) => n.length).value(), e = Object.keys(u), w = e.map((n) => p("{rating} star", { rating: n })), x = e.map((n) => u[n]); 85 return { labels: w, datasets: [{ label: p("Count"), data: x, backgroundColor: Object.values(S) }] }; 86 }), i = h(() => ({ responsive: true, maintainAspectRatio: false, plugins: { legend: { display: true, position: "bottom" } } })); 87 return (u, e) => (f(), b("div", De, [a("div", Re, v(s(p)("Organizations")), 1), a("div", null, [m(s(z), { data: r.value, options: i.value, style: { height: "324px", width: "100%" } }, null, 8, ["data", "options"])])])); 88} }, Ce = { class: "mb-6 flex items-center justify-between" }, qe = { class: "text-lg font-semibold text-black" }, Ae = { class: "max-lg:w-full max-lg:max-w-0" }, Oe = { class: "truncate pr-4 text-sm font-medium text-gray-900 max-lg:hidden lg:pl-6" }, Me = { class: "py-3 lg:hidden" }, Be = { class: "flex items-center justify-between gap-3" }, Ye = { class: "truncate text-sm font-medium text-gray-900" }, je = { class: "truncate text-sm text-gray-500" }, ze = { key: 0, class: "mt-1 line-clamp-2 whitespace-normal text-sm text-gray-700" }, Se = { class: "mt-1 flex items-center justify-between gap-3" }, Le = { class: "hidden lg:table-cell" }, Te = { class: "hidden pr-4 text-sm text-gray-500 lg:block" }, Ve = { class: "hidden lg:table-cell" }, Ee = { class: "max-w-60 truncate text-sm font-medium leading-5 text-gray-900 hover:text-primary-600" }, Ie = { class: "hidden lg:table-cell" }, Ne = { class: "hidden lg:table-cell" }, Ue = { class: "hidden max-w-60 truncate lg:block" }, Fe = { class: "hidden lg:table-cell" }, Pe = { class: "hidden text-sm font-medium text-gray-500 lg:block" }, He = { class: "hidden lg:table-cell" }, We = { class: "hidden lg:block" }, Ge = { key: 1, class: "text-sm text-gray-500" }, Je = { __name: "RatingReportTable", props: { reviews: { type: Array, required: true } }, setup(d) { 89 const { t: o } = D(), p = te([{ key: "client", label: o("Client"), showing: true, position: 1 }, { key: "organization", label: o("Organization"), showing: true, position: 2 }, { key: "request", label: o("Request"), showing: true, position: 3 }, { key: "rating", label: o("Rating"), showing: true, position: 4 }, { key: "review", label: o("Review"), showing: true, position: 5 }, { key: "created_at", label: o("Date"), showing: true, position: 6 }, { key: "assignees", label: o("Assigned to"), showing: true, position: 7 }]); 90 return (r, i) => { 91 const u = se("tooltip"); 92 return f(), b("div", null, [a("div", Ce, [a("div", qe, v(s(o)("Recent reviews")), 1), m(de, { "route-name": "reports.reviews.export", filename: "reviews.csv" })]), m(ce, { data: d.reviews, columns: p.value }, { client: k(({ item: e }) => [a("td", Ae, [a("div", Oe, v(e.request.client.name), 1), a("div", Me, [a("div", Be, [a("span", Ye, v(e.request.client.name), 1), m(F, { stars: e.rating, class: "shrink-0 !text-base" }, null, 8, ["stars"])]), a("p", je, v(e.request.organization.name) + " \xB7 " + v(s(E)(e.created_at, "MMM D, YYYY")), 1), e.comment ? (f(), b("p", ze, v(e.comment), 1)) : V("", true), a("div", Se, [m(s(N), { href: s(P)(e.request.slug), class: "min-w-0 truncate text-sm font-medium text-primary-600 after:absolute after:inset-0" }, { default: k(() => [B(v(e.request.title), 1)]), _: 2 }, 1032, ["href"]), e.request.users.length ? (f(), I(U, { key: 0, "selected-users": e.request.users, options: { assignable: false }, class: "relative shrink-0 [&_button]:relative [&_button]:after:absolute [&_button]:after:-inset-y-2.5 [&_button]:after:inset-x-0 [&_button]:after:content-['']" }, null, 8, ["selected-users"])) : V("", true)])])])]), organization: k(({ item: e }) => [a("td", Le, [a("div", Te, v(e.request.organization.name), 1)])]), request: k(({ item: e }) => [a("td", Ve, [a("div", Ee, [m(s(N), { href: s(P)(e.request.slug), title: e.request.title }, { default: k(() => [B(v(e.request.title), 1)]), _: 2 }, 1032, ["href", "title"])])])]), rating: k(({ item: e }) => [a("td", Ie, [m(F, { stars: e.rating, class: "hidden pr-4 lg:block" }, null, 8, ["stars"])])]), review: k(({ item: e }) => [a("td", Ne, [ae((f(), b("div", Ue, [B(v(e.comment), 1)])), [[u, e.comment]])])]), created_at: k(({ item: e }) => [a("td", Fe, [a("div", Pe, v(s(E)(e.created_at, "MMM D, YYYY")), 1)])]), assignees: k(({ item: e }) => [a("td", He, [a("div", We, [e.request.users.length ? (f(), I(U, { key: 0, "selected-users": e.request.users, options: { assignable: false } }, null, 8, ["selected-users"])) : (f(), b("div", Ge, "-"))])])]), _: 1 }, 8, ["data", "columns"])]); 93 }; 94} }, Ke = { class: "rounded-md bg-white p-6 shadow" }, Qe = { class: "mb-6 font-semibold leading-tight text-gray-900" }, Xe = { __name: "RatingServiceChart", props: { reviews: { type: Array, required: true } }, setup(d) { 95 $.register(j, A, O, q, C); 96 const o = d, { t: p } = D(), r = h(() => { 97 const u = _.chain(o.reviews).groupBy((n) => n.request.service.name).mapValues((n) =>
97 n.length).value(), e = Object.keys(u), w = e.map((n) => p("{rating} star", { rating: n })), x = e.map((n) => u[n]); 98 return { labels: w, datasets: [{ label: p("Count"), data: x, backgroundColor: Object.values(S) }] }; 99 }), i = h(() => ({ responsive: true, maintainAspectRatio: false, plugins: { legend: { display: true, position: "bottom" } } })); 100 return (u, e) => (f(), b("div", Ke, [a("div", Qe, v(s(p)("Services")), 1), a("div", null, [m(s(z), { data: r.value, options: i.value, style: { height: "324px", width: "100%" } }, null, 8, ["data", "options"])])])); 101} }, Ze = { class: "rounded-md bg-white p-6 shadow" }, et = { class: "mb-6 font-semibold leading-tight text-gray-900" }, tt = { __name: "RatingTeamChart", props: { reviews: { type: Array, required: true } }, setup(d) { 102 $.register(j, A, O, q, C); 103 const o = d, { t: p } = D(), r = h(() => { 104 const u = _.flatMap(o.reviews, (y) => y.request.users.map((R) => ({ user_id: R.id, user_name: R.name, review_id: y.id }))), e = _.groupBy(u, "user_id"), w = _.mapValues(e, (y) => ({ count: y.length, name: y[0].user_name })), x = Object.values(w).map((y) => y.name), n = Object.values(w).map((y) => y.count); 105 return { labels: x, datasets: [{ label: p("Count"), data: n, backgroundColor: Object.values(S) }] }; 106 }), i = h(() => ({ responsive: true, maintainAspectRatio: false, plugins: { legend: { display: true, position: "bottom" } } })); 107 return (u, e) => (f(), b("div", Ze, [a("div", et, v(s(p)("Team member")), 1), a("div", null, [m(s(z), { data: r.value, options: i.value, style: { height: "324px", width: "100%" } }, null, 8, ["data", "options"])])])); 108} }, st = { key: 0, class: "p-8 sm:p-20" }, at = { class: "m-auto text-center" }, rt = { class: "mb-3 text-xl font-semibold text-gray-900" }, ot = { key: 1, class: "rounded-md border bg-white shadow" }, it = { class: "p-4 text-base font-semibold text-black" }, nt = { class: "p-2" }, lt = { __name: "ReviewsBarChart", props: { reviews: { type: Object, required: true }, startDate: { type: [String, Date], required: false }, endDate: { type: [String, Date], required: false } }, setup(d) { 109 const { t: o } = D(), p = H(W).smaller("sm"); 110 $.register(C, q, G, J, K, A, O, Q); 111 const r = d, i = h(() => { 112 const l = g(r.startDate ?? g().subtract(1, "month")), t = g(r.endDate ?? g()); 113 let c = "day"; 114 return t.diff(l, "day") >= 35 && (c = "week"), t.diff(l, "day") >= 180 && (c = "month"), c; 115 }), u = (l) => { 116 const t = g(l.created_at).tz("UTC"); 117 return i.value === "day" ? t.format("YYYY-MM-DD") : i.value === "week" ? t.week() : t.format("MMM"); 118 }, e = h(() => { 119 const l = _.groupBy(_.cloneDeep(r.reviews), u); 120 return Y.mapValues(l, (t) => t.filter((c) => c.id).length); 121 }), w = h(() => _.sum(Object.values(e.value))), x = h(() => w.value === 0), n = (l) => l.sort((t, c) => i.value === "day" ? g(t).isBefore(g(c)) ? -1 : 1 : i.value === "week" ? t - c : g(`01 ${t}`).isBefore(g(`01 ${c}`)) ? -1 : 1), y = (l) => l.map((t) => i.value === "day" ? (t = g(t), t.format("DD MMM")) : i.value === "week" ? o("Week {week}", { week: t }) : t), R = h(() => { 122 const l = e.value, t = n(Object.keys(l)), c = y(t), M = t.map((T) => l[T]); 123 return { labels: c, datasets: [{ label: o("Reviews"), backgroundColor: "rgba(79,70,229,1)", data: M, borderRadius: 8 }] }; 124 }), L = h(() => ({ responsive: true, maintainAspectRatio: false, plugins: { title: { display: true, text: o("Total reviews in selected period: {count}", { count: w.value }), padding: { top: 10, bottom: 30 } }, tooltip: { mode: "index", intersect: false }, legend: { display: false } }, scales: { y: { ticks: { color: "#A3A3A3" }, grid: { display: false }, stacked: true }, x: { ticks: { color: "#A3A3A3", ...p.value ? { maxTicksLimit: 5, maxRotation: 0, minRotation: 0 } : { maxTicksLimit: 10, maxRotation: 45, minRotation: 45 } }, grid: { display: false }, stacked: true } } })); 125 return (l, t) => x.value ? (f(), b("div", st, [a("div", at, [m(s(Z), { class: "mx-auto mb-5 h-12 w-12 stroke-2 text-gray-400" }), a("h3", rt, v(s(o)("No reviews yet")), 1)])])) : (f(), b("div", ot, [a("div", it, v(s(o)("Reviews")), 1), a("div", nt, [m(s(X), { data: R.value, options: L.value, style: { height: "307px", width: "100%" } }, null, 8, ["data", "options"])])])); 126} }, dt = { class: "rounded-md bg-white p-6 shadow max-sm:bg-transparent max-sm:p-0 max-sm:shadow-none" }, ct = { key: 0, class: "space-y-6" }, ut = { class: "grid grid-cols-1 gap-4 lg:grid-cols-2" }, mt = { class: "grid grid-cols-1 gap-4 lg:grid-cols-4" }
126, pt = { key: 1, class: "flex flex-col" }, _t = { class: "p-8 sm:p-20" }, gt = { class: "m-auto text-center" }, vt = { class: "mb-3 text-xl font-semibold text-gray-900" }, ht = { key: 0, class: "rounded-md bg-white p-6 shadow max-sm:p-4" }, ws = { __name: "ReviewsReport", props: { allClients: { type: Array, required: true }, teamUsers: { type: Array, required: true }, services: { type: Array, required: true }, organizations: { type: Array, required: true }, reviews: { type: Array, required: true } }, setup(d) { 127 var _a, _b, _c, _d; 128 const { t: o } = D(), p = [{ label: o("Dashboard"), url: route("dashboard") }, { label: o("Requests report") }], r = re({ selected_organizations: ((_a = route().params.selected_organizations) == null ? void 0 : _a.map((i) => parseInt(i))) ?? [], selected_clients: ((_b = route().params.selected_clients) == null ? void 0 : _b.map((i) => parseInt(i))) ?? [], selected_team_users: ((_c = route().params.selected_team_users) == null ? void 0 : _c.map((i) => parseInt(i))) ?? [], selected_services: ((_d = route().params.selected_services) == null ? void 0 : _d.map((i) => parseInt(i))) ?? [], start_date: route().params.start_date ?? g().subtract(1, "month").format("YYYY-MM-DD"), end_date: route().params.end_date ?? g().format("YYYY-MM-DD") }); 129 return oe([() => r.selected_organizations, () => r.selected_clients, () => r.selected_team_users, () => r.selected_services, () => r.start_date, () => r.end_date], () => r.transform((i) => _.omitBy(i, (u) => u === null)).get(route("reports.reviews"), { preserveState: true, preserveScroll: true })), (i, u) => (f(), b(le, null, [m(s(ie), { title: s(o)("Reviews report") }, null, 8, ["title"]), m(me, { breadcrumbs: p, "wrapper-class": "bg-transparent space-y-10 shadow-none overflow-visible" }, { header: k(() => [B(v(s(o)("Reviews report")), 1)]), default: k(() => [a("div", dt, [m(ue, { modelValue: s(r), "onUpdate:modelValue": u[0] || (u[0] = (e) => ne(r) ? r.value = e : null), "team-users": d.teamUsers, clients: d.allClients, services: d.services, organizations: d.organizations, tags: [], class: "mb-7" }, null, 8, ["modelValue", "team-users", "clients", "services", "organizations"]), s(Y.isEmpty)(d.reviews) ? (f(), b("div", pt, [a("div", _t, [a("div", gt, [m(s(pe), { class: "mx-auto mb-5 h-12 w-12 stroke-2 text-gray-500" }), a("h3", vt, v(s(o)("No reviews for the selected period")), 1)])])])) : (f(), b("div", ct, [a("div", ut, [m(lt, { reviews: d.reviews, "start-date": s(r).start_date, "end-date": s(r).end_date }, null, 8, ["reviews", "start-date", "end-date"]), m(we, { reviews: d.reviews, "start-date": s(r).start_date, "end-date": s(r).end_date }, null, 8, ["reviews", "start-date", "end-date"])]), a("div", mt, [m(ke, { reviews: d.reviews, "start-date": s(r).start_date, "end-date": s(r).end_date }, null, 8, ["reviews", "start-date", "end-date"]), m(tt, { reviews: d.reviews, "start-date": s(r).start_date, "end-date": s(r).end_date }, null, 8, ["reviews", "start-date", "end-date"]), m($e, { reviews: d.reviews, "start-date": s(r).start_date, "end-date": s(r).end_date }, null, 8, ["reviews", "start-date", "end-date"]), m(Xe, { reviews: d.reviews, "start-date": s(r).start_date, "end-date": s(r).end_date }, null, 8, ["reviews", "start-date", "end-date"])])]))]), s(Y.isEmpty)(d.reviews) ? V("", true) : (f(), b("div", ht, [m(Je, { reviews: d.reviews }, null, 8, ["reviews"])]))]), _: 1 })], 64)); 130} }; 131export { 132 ws as default 133};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.