@burdenoff/microfe-crewfoundry 2026.1029.2 → 2026.1030.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crewfoundry/lib/useFocusedRecordParam.d.ts +51 -0
- package/dist/crewfoundry/lib/useFocusedRecordParam.d.ts.map +1 -0
- package/dist/crewfoundry/lib/useFocusedRecordParam.js +38 -0
- package/dist/crewfoundry/lib/useFocusedRecordParam.js.map +1 -0
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +119 -112
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +78 -71
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +88 -81
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +133 -126
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +150 -143
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +110 -103
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +173 -162
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrPayrollPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/HrPayrollPagePage.js +169 -158
- package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.d.ts.map +1 -1
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +179 -163
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
- package/dist/utils/pageContext.d.ts +43 -4
- package/dist/utils/pageContext.d.ts.map +1 -1
- package/dist/utils/pageContext.js +10 -3
- package/dist/utils/pageContext.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The search param that names the record a page is focused on.
|
|
3
|
+
*
|
|
4
|
+
* It is the same `?id=` the detail pages (`hiring/job-details-page?id=…`)
|
|
5
|
+
* already read, so `resolveCrewFoundryConversationContext` in
|
|
6
|
+
* `src/utils/pageContext.ts` resolves every focused record the same way: the
|
|
7
|
+
* assistant's "this interview" / "approve this" works without the user naming
|
|
8
|
+
* the record.
|
|
9
|
+
*/
|
|
10
|
+
export declare const FOCUSED_RECORD_PARAM = "id";
|
|
11
|
+
interface UseFocusedRecordParamOptions<T extends {
|
|
12
|
+
id: string;
|
|
13
|
+
}> {
|
|
14
|
+
/** The records the page can focus. Restoring waits until the URL's id is among them. */
|
|
15
|
+
records: readonly T[];
|
|
16
|
+
/** The record the page is showing right now (selected row, open edit dialog), or null. */
|
|
17
|
+
activeId: string | null;
|
|
18
|
+
/** Re-focus the record named by the URL when the page is opened from a link or reloaded. */
|
|
19
|
+
onRestore: (record: T) => void;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Keeps `?id=` in step with the record a list page is focused on.
|
|
23
|
+
*
|
|
24
|
+
* List pages (leave, time, payroll, interviews, departments, clients, vendors,
|
|
25
|
+
* announcements, candidates) have no detail route of their own: the user
|
|
26
|
+
* focuses a record in place, by selecting a row or opening its edit dialog.
|
|
27
|
+
* Writing that focus to the URL is what lets the assistant's page context name
|
|
28
|
+
* the record, and makes the focused record linkable.
|
|
29
|
+
*
|
|
30
|
+
* - On first load, an `?id=` already in the URL is restored once, as soon as
|
|
31
|
+
* the record is loaded (`onRestore`). Until then the id is left alone, so a
|
|
32
|
+
* slow list load cannot erase a deep link.
|
|
33
|
+
* - After that, the URL follows `activeId`: set while a record is focused,
|
|
34
|
+
* removed when focus is cleared. Updates use `replace` so focusing rows does
|
|
35
|
+
* not fill the browser history.
|
|
36
|
+
*/
|
|
37
|
+
export declare function useFocusedRecordParam<T extends {
|
|
38
|
+
id: string;
|
|
39
|
+
}>({ records, activeId, onRestore, }: UseFocusedRecordParamOptions<T>): void;
|
|
40
|
+
/**
|
|
41
|
+
* Marks the focused row's primary cell. `ResponsiveTable` has no row-state
|
|
42
|
+
* styling, so the highlight sits on the cell; the classes match the selected
|
|
43
|
+
* state of the interview schedule list.
|
|
44
|
+
*/
|
|
45
|
+
export declare const FOCUSED_CELL_CLASS = "rounded-[var(--radius-input)] bg-action-primary-bg/10 ring-1 ring-action-primary-bg";
|
|
46
|
+
/** The 1-based `usePagination` page that holds `id` in `list` (1 when it is absent). */
|
|
47
|
+
export declare function pageContaining(list: readonly {
|
|
48
|
+
id: string;
|
|
49
|
+
}[], id: string, pageSize: number): number;
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=useFocusedRecordParam.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFocusedRecordParam.d.ts","sourceRoot":"","sources":["../../../src/crewfoundry/lib/useFocusedRecordParam.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,UAAU,4BAA4B,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE;IAC7D,wFAAwF;IACxF,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;IACtB,0FAA0F;IAC1F,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,4FAA4F;IAC5F,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;CAChC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,EAC9D,OAAO,EACP,QAAQ,EACR,SAAS,GACV,EAAE,4BAA4B,CAAC,CAAC,CAAC,GAAG,IAAI,CA6DxC;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,wFACwD,CAAC;AAExF,wFAAwF;AACxF,wBAAgB,cAAc,CAC5B,IAAI,EAAE,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,EAC/B,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,MAAM,GACf,MAAM,CAGR"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useEffect as e, useRef as t } from "react";
|
|
2
|
+
import { useSearchParams as n } from "react-router";
|
|
3
|
+
function r({ records: r, activeId: i, onRestore: a }) {
|
|
4
|
+
let [o, s] = n(), c = o.get("id"), l = t(c === null), u = t(null), d = t(a), f = t(c), p = t(s);
|
|
5
|
+
e(() => {
|
|
6
|
+
d.current = a, f.current = c, p.current = s;
|
|
7
|
+
}), e(() => {
|
|
8
|
+
if (l.current) return;
|
|
9
|
+
if (c === null) {
|
|
10
|
+
l.current = !0;
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
let e = r.find((e) => e.id === c);
|
|
14
|
+
e && (l.current = !0, u.current = e.id, d.current(e));
|
|
15
|
+
}, [r, c]), e(() => {
|
|
16
|
+
if (!l.current) {
|
|
17
|
+
if (i === null) return;
|
|
18
|
+
l.current = !0;
|
|
19
|
+
}
|
|
20
|
+
if (u.current !== null) {
|
|
21
|
+
if (i !== u.current) return;
|
|
22
|
+
u.current = null;
|
|
23
|
+
}
|
|
24
|
+
i !== f.current && p.current((e) => {
|
|
25
|
+
let t = new URLSearchParams(e);
|
|
26
|
+
return i ? t.set("id", i) : t.delete("id"), t;
|
|
27
|
+
}, { replace: !0 });
|
|
28
|
+
}, [i]);
|
|
29
|
+
}
|
|
30
|
+
var i = "rounded-[var(--radius-input)] bg-action-primary-bg/10 ring-1 ring-action-primary-bg";
|
|
31
|
+
function a(e, t, n) {
|
|
32
|
+
let r = e.findIndex((e) => e.id === t);
|
|
33
|
+
return r < 0 || n <= 0 ? 1 : Math.floor(r / n) + 1;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { i as FOCUSED_CELL_CLASS, a as pageContaining, r as useFocusedRecordParam };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=useFocusedRecordParam.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFocusedRecordParam.js","names":[],"sources":["../../../src/crewfoundry/lib/useFocusedRecordParam.ts"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport { useSearchParams } from 'react-router';\n\n/**\n * The search param that names the record a page is focused on.\n *\n * It is the same `?id=` the detail pages (`hiring/job-details-page?id=…`)\n * already read, so `resolveCrewFoundryConversationContext` in\n * `src/utils/pageContext.ts` resolves every focused record the same way: the\n * assistant's \"this interview\" / \"approve this\" works without the user naming\n * the record.\n */\nexport const FOCUSED_RECORD_PARAM = 'id';\n\ninterface UseFocusedRecordParamOptions<T extends { id: string }> {\n /** The records the page can focus. Restoring waits until the URL's id is among them. */\n records: readonly T[];\n /** The record the page is showing right now (selected row, open edit dialog), or null. */\n activeId: string | null;\n /** Re-focus the record named by the URL when the page is opened from a link or reloaded. */\n onRestore: (record: T) => void;\n}\n\n/**\n * Keeps `?id=` in step with the record a list page is focused on.\n *\n * List pages (leave, time, payroll, interviews, departments, clients, vendors,\n * announcements, candidates) have no detail route of their own: the user\n * focuses a record in place, by selecting a row or opening its edit dialog.\n * Writing that focus to the URL is what lets the assistant's page context name\n * the record, and makes the focused record linkable.\n *\n * - On first load, an `?id=` already in the URL is restored once, as soon as\n * the record is loaded (`onRestore`). Until then the id is left alone, so a\n * slow list load cannot erase a deep link.\n * - After that, the URL follows `activeId`: set while a record is focused,\n * removed when focus is cleared. Updates use `replace` so focusing rows does\n * not fill the browser history.\n */\nexport function useFocusedRecordParam<T extends { id: string }>({\n records,\n activeId,\n onRestore,\n}: UseFocusedRecordParamOptions<T>): void {\n const [searchParams, setSearchParams] = useSearchParams();\n const urlId = searchParams.get(FOCUSED_RECORD_PARAM);\n\n // The initial URL id is restored at most once; afterwards the page owns focus.\n const restoredRef = useRef<boolean>(urlId === null);\n // Set while a restored record has been handed to the page but the page's\n // focus has not caught up yet, so the sync below does not erase the id in\n // the render between the two.\n const awaitingFocusRef = useRef<string | null>(null);\n const onRestoreRef = useRef(onRestore);\n // Read the latest URL state inside the sync effect without re-running it on\n // every navigation: it must fire only when the page's focus changes.\n const urlIdRef = useRef(urlId);\n const setSearchParamsRef = useRef(setSearchParams);\n\n // Runs before the effects below in every commit, so they see this render's values.\n useEffect(() => {\n onRestoreRef.current = onRestore;\n urlIdRef.current = urlId;\n setSearchParamsRef.current = setSearchParams;\n });\n\n useEffect(() => {\n if (restoredRef.current) return;\n if (urlId === null) {\n restoredRef.current = true;\n return;\n }\n const record = records.find((candidate) => candidate.id === urlId);\n if (!record) return;\n restoredRef.current = true;\n awaitingFocusRef.current = record.id;\n onRestoreRef.current(record);\n }, [records, urlId]);\n\n useEffect(() => {\n if (!restoredRef.current) {\n // The linked record never loaded (deleted, or not visible to this\n // user). Once the user focuses something else, the page owns the URL.\n if (activeId === null) return;\n restoredRef.current = true;\n }\n if (awaitingFocusRef.current !== null) {\n if (activeId !== awaitingFocusRef.current) return;\n awaitingFocusRef.current = null;\n }\n if (activeId === urlIdRef.current) return;\n setSearchParamsRef.current(\n (previous) => {\n const next = new URLSearchParams(previous);\n if (activeId) {\n next.set(FOCUSED_RECORD_PARAM, activeId);\n } else {\n next.delete(FOCUSED_RECORD_PARAM);\n }\n return next;\n },\n { replace: true }\n );\n }, [activeId]);\n}\n\n/**\n * Marks the focused row's primary cell. `ResponsiveTable` has no row-state\n * styling, so the highlight sits on the cell; the classes match the selected\n * state of the interview schedule list.\n */\nexport const FOCUSED_CELL_CLASS =\n 'rounded-[var(--radius-input)] bg-action-primary-bg/10 ring-1 ring-action-primary-bg';\n\n/** The 1-based `usePagination` page that holds `id` in `list` (1 when it is absent). */\nexport function pageContaining(\n list: readonly { id: string }[],\n id: string,\n pageSize: number\n): number {\n const index = list.findIndex((item) => item.id === id);\n return index < 0 || pageSize <= 0 ? 1 : Math.floor(index / pageSize) + 1;\n}\n"],"mappings":";;AAuCA,SAAgB,EAAgD,EAC9D,YACA,aACA,gBACwC;CACxC,IAAM,CAAC,GAAc,KAAmB,GAAiB,EACnD,IAAQ,EAAa,IAAA,KAAyB,EAG9C,IAAc,EAAgB,MAAU,KAAK,EAI7C,IAAmB,EAAsB,KAAK,EAC9C,IAAe,EAAO,EAAU,EAGhC,IAAW,EAAO,EAAM,EACxB,IAAqB,EAAO,EAAgB;AAsBlD,CAnBA,QAAgB;AAGd,EAFA,EAAa,UAAU,GACvB,EAAS,UAAU,GACnB,EAAmB,UAAU;GAC7B,EAEF,QAAgB;AACd,MAAI,EAAY,QAAS;AACzB,MAAI,MAAU,MAAM;AAClB,KAAY,UAAU;AACtB;;EAEF,IAAM,IAAS,EAAQ,MAAM,MAAc,EAAU,OAAO,EAAM;AAC7D,QACL,EAAY,UAAU,IACtB,EAAiB,UAAU,EAAO,IAClC,EAAa,QAAQ,EAAO;IAC3B,CAAC,GAAS,EAAM,CAAC,EAEpB,QAAgB;AACd,MAAI,CAAC,EAAY,SAAS;AAGxB,OAAI,MAAa,KAAM;AACvB,KAAY,UAAU;;AAExB,MAAI,EAAiB,YAAY,MAAM;AACrC,OAAI,MAAa,EAAiB,QAAS;AAC3C,KAAiB,UAAU;;AAEzB,QAAa,EAAS,WAC1B,EAAmB,SAChB,MAAa;GACZ,IAAM,IAAO,IAAI,gBAAgB,EAAS;AAM1C,UALI,IACF,EAAK,IAAA,MAA0B,EAAS,GAExC,EAAK,OAAA,KAA4B,EAE5B;KAET,EAAE,SAAS,IAAM,CAClB;IACA,CAAC,EAAS,CAAC;;AAQhB,IAAa,IACX;AAGF,SAAgB,EACd,GACA,GACA,GACQ;CACR,IAAM,IAAQ,EAAK,WAAW,MAAS,EAAK,OAAO,EAAG;AACtD,QAAO,IAAQ,KAAK,KAAY,IAAI,IAAI,KAAK,MAAM,IAAQ,EAAS,GAAG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommunicationsAnnouncementsPagePage.d.ts","sourceRoot":"","sources":["../../../src/crewfoundry/pages/CommunicationsAnnouncementsPagePage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CommunicationsAnnouncementsPagePage.d.ts","sourceRoot":"","sources":["../../../src/crewfoundry/pages/CommunicationsAnnouncementsPagePage.tsx"],"names":[],"mappings":"AAkHA,wBAAgB,mCAAmC,gCAuVlD"}
|
|
@@ -2,12 +2,13 @@ import { CONVERSATIONS_ROUTE as e, useCrewFoundryStore as t } from "../store/cre
|
|
|
2
2
|
import { formatEnumLabel as n } from "../utils/formatEnumLabel.js";
|
|
3
3
|
import { AvatarStack as r } from "../components/viz/AvatarStack.js";
|
|
4
4
|
import "../components/viz/index.js";
|
|
5
|
-
import { FormModal as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
5
|
+
import { FormModal as i, useFormModal as a } from "../components/forms/FormModal.js";
|
|
6
|
+
import { useFocusedRecordParam as ee } from "../lib/useFocusedRecordParam.js";
|
|
7
|
+
import { useMemo as o, useState as s } from "react";
|
|
8
|
+
import { Eye as te, MessageSquare as ne, Pencil as re, Pin as c, PinOff as ie, Plus as l, Search as u, Send as d, Trash2 as f } from "lucide-react";
|
|
9
|
+
import { useNavigate as p } from "react-router";
|
|
10
|
+
import { jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
11
|
+
import { AlertDialog as g, AlertDialogAction as _, AlertDialogCancel as ae, AlertDialogContent as oe, AlertDialogDescription as se, AlertDialogFooter as ce, AlertDialogHeader as le, AlertDialogTitle as ue, Badge as v, Button as y, Card as de, CardContent as b, CardHeader as x, CardTitle as S, GlassCard as fe, GradientText as C, IllustratedEmptyState as w, Input as T, PagePurpose as E } from "@burdenoff/fe-libs/ui";
|
|
11
12
|
import { useGlobalUi as D } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
12
13
|
import { formatRelativeTime as O } from "@burdenoff/fe-libs/shared/utils";
|
|
13
14
|
//#region src/crewfoundry/pages/CommunicationsAnnouncementsPagePage.tsx
|
|
@@ -123,10 +124,16 @@ var k = [
|
|
|
123
124
|
}
|
|
124
125
|
};
|
|
125
126
|
function I() {
|
|
126
|
-
let { announcements: O, notifications: k, addAnnouncement: A, updateAnnouncement: I, removeAnnouncement: L } = t(), { showToast: R } = D(),
|
|
127
|
+
let { announcements: O, notifications: k, addAnnouncement: A, updateAnnouncement: I, removeAnnouncement: L } = t(), { showToast: R } = D(), pe = p(), z = a();
|
|
128
|
+
ee({
|
|
129
|
+
records: O,
|
|
130
|
+
activeId: z.open ? z.context?.id ?? null : null,
|
|
131
|
+
onRestore: z.openModal
|
|
132
|
+
});
|
|
133
|
+
let [B, V] = s(null), [H, U] = s(!1), [W, me] = s(""), G = z.context, K = o(() => k.filter((e) => e.category === "communications"), [k]), q = W.trim().toLowerCase(), J = o(() => q.length === 0 ? O : O.filter((e) => `${e.title} ${e.content} ${e.tags.join(" ")}`.toLowerCase().includes(q)), [O, q]), Y = J.filter((e) => e.isPinned), X = J.filter((e) => !e.isPinned), he = async (e) => {
|
|
127
134
|
let t = Array.isArray(e.tags) ? e.tags : [];
|
|
128
|
-
if (
|
|
129
|
-
await I(
|
|
135
|
+
if (G) {
|
|
136
|
+
await I(G.id, {
|
|
130
137
|
title: String(e.title),
|
|
131
138
|
content: String(e.content),
|
|
132
139
|
category: String(e.category),
|
|
@@ -149,117 +156,117 @@ function I() {
|
|
|
149
156
|
viewCount: 0,
|
|
150
157
|
tags: t
|
|
151
158
|
}), R("Announcement published", "success");
|
|
152
|
-
},
|
|
159
|
+
}, ge = async (e) => {
|
|
153
160
|
try {
|
|
154
161
|
await I(e.id, { isPinned: !e.isPinned }), R(e.isPinned ? "Unpinned" : "Pinned to top", "success");
|
|
155
162
|
} catch (e) {
|
|
156
163
|
R(e instanceof Error ? e.message : "Unable to update announcement", "error");
|
|
157
164
|
}
|
|
158
|
-
},
|
|
159
|
-
if (
|
|
160
|
-
|
|
165
|
+
}, _e = async () => {
|
|
166
|
+
if (B) {
|
|
167
|
+
U(!0);
|
|
161
168
|
try {
|
|
162
|
-
await L(
|
|
169
|
+
await L(B.id), R("Announcement deleted", "success"), V(null);
|
|
163
170
|
} catch (e) {
|
|
164
171
|
R(e instanceof Error ? e.message : "Unable to delete announcement", "error");
|
|
165
172
|
} finally {
|
|
166
|
-
|
|
173
|
+
U(!1);
|
|
167
174
|
}
|
|
168
175
|
}
|
|
169
|
-
},
|
|
170
|
-
title:
|
|
171
|
-
content:
|
|
172
|
-
category:
|
|
173
|
-
priority:
|
|
174
|
-
tags:
|
|
175
|
-
isPinned:
|
|
176
|
-
} : void 0, $ = (e, t) => /* @__PURE__ */
|
|
176
|
+
}, Z = () => pe(e), Q = G ? {
|
|
177
|
+
title: G.title,
|
|
178
|
+
content: G.content,
|
|
179
|
+
category: G.category,
|
|
180
|
+
priority: G.priority,
|
|
181
|
+
tags: G.tags,
|
|
182
|
+
isPinned: G.isPinned
|
|
183
|
+
} : void 0, $ = (e, t) => /* @__PURE__ */ h(fe, {
|
|
177
184
|
treatment: t ? "glass" : "plain",
|
|
178
185
|
glow: t,
|
|
179
186
|
className: "transition-shadow hover:shadow-elevation-2",
|
|
180
|
-
children: [/* @__PURE__ */
|
|
187
|
+
children: [/* @__PURE__ */ h(x, {
|
|
181
188
|
className: "pb-3",
|
|
182
|
-
children: [/* @__PURE__ */
|
|
189
|
+
children: [/* @__PURE__ */ h("div", {
|
|
183
190
|
className: "flex items-start justify-between gap-3",
|
|
184
|
-
children: [/* @__PURE__ */
|
|
191
|
+
children: [/* @__PURE__ */ h("div", {
|
|
185
192
|
className: "flex flex-wrap items-center gap-2",
|
|
186
193
|
children: [
|
|
187
|
-
/* @__PURE__ */
|
|
194
|
+
/* @__PURE__ */ m(v, {
|
|
188
195
|
className: `border-transparent text-[10px] ${M[e.priority]}`,
|
|
189
196
|
children: n(e.priority)
|
|
190
197
|
}),
|
|
191
|
-
/* @__PURE__ */
|
|
198
|
+
/* @__PURE__ */ m(v, {
|
|
192
199
|
className: `border-transparent text-[10px] ${j[e.category]}`,
|
|
193
200
|
children: n(e.category)
|
|
194
201
|
}),
|
|
195
|
-
/* @__PURE__ */
|
|
202
|
+
/* @__PURE__ */ h("span", {
|
|
196
203
|
className: "flex items-center gap-1.5 text-xs text-text-secondary",
|
|
197
204
|
children: [
|
|
198
|
-
/* @__PURE__ */
|
|
205
|
+
/* @__PURE__ */ m(r, {
|
|
199
206
|
people: [{ name: e.author }],
|
|
200
207
|
size: 20
|
|
201
208
|
}),
|
|
202
209
|
e.author,
|
|
203
|
-
/* @__PURE__ */
|
|
210
|
+
/* @__PURE__ */ h("span", {
|
|
204
211
|
className: "text-text-muted",
|
|
205
212
|
children: ["· ", F(e.createdAt)]
|
|
206
213
|
})
|
|
207
214
|
]
|
|
208
215
|
})
|
|
209
216
|
]
|
|
210
|
-
}), /* @__PURE__ */
|
|
217
|
+
}), /* @__PURE__ */ h("div", {
|
|
211
218
|
className: "flex items-center gap-0.5",
|
|
212
219
|
children: [
|
|
213
|
-
/* @__PURE__ */
|
|
220
|
+
/* @__PURE__ */ m(y, {
|
|
214
221
|
variant: "ghost",
|
|
215
222
|
size: "icon",
|
|
216
223
|
className: `h-7 w-7 ${e.isPinned ? "text-status-info-text" : ""}`,
|
|
217
224
|
"aria-label": e.isPinned ? `Unpin ${e.title}` : `Pin ${e.title}`,
|
|
218
225
|
"aria-pressed": e.isPinned,
|
|
219
|
-
onClick: () => void
|
|
220
|
-
children: e.isPinned ? /* @__PURE__ */
|
|
226
|
+
onClick: () => void ge(e),
|
|
227
|
+
children: e.isPinned ? /* @__PURE__ */ m(ie, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ m(c, { className: "h-3.5 w-3.5" })
|
|
221
228
|
}),
|
|
222
|
-
/* @__PURE__ */
|
|
229
|
+
/* @__PURE__ */ m(y, {
|
|
223
230
|
variant: "ghost",
|
|
224
231
|
size: "icon",
|
|
225
232
|
className: "h-7 w-7",
|
|
226
233
|
"aria-label": `Edit announcement ${e.title}`,
|
|
227
|
-
onClick: () =>
|
|
228
|
-
children: /* @__PURE__ */
|
|
234
|
+
onClick: () => z.openModal(e),
|
|
235
|
+
children: /* @__PURE__ */ m(re, { className: "h-3.5 w-3.5" })
|
|
229
236
|
}),
|
|
230
|
-
/* @__PURE__ */
|
|
237
|
+
/* @__PURE__ */ m(y, {
|
|
231
238
|
variant: "ghost",
|
|
232
239
|
size: "icon",
|
|
233
240
|
className: "h-7 w-7 text-status-error-text",
|
|
234
241
|
"aria-label": `Delete announcement ${e.title}`,
|
|
235
|
-
onClick: () =>
|
|
236
|
-
children: /* @__PURE__ */
|
|
242
|
+
onClick: () => V(e),
|
|
243
|
+
children: /* @__PURE__ */ m(f, { className: "h-3.5 w-3.5" })
|
|
237
244
|
})
|
|
238
245
|
]
|
|
239
246
|
})]
|
|
240
|
-
}), /* @__PURE__ */
|
|
247
|
+
}), /* @__PURE__ */ m(S, {
|
|
241
248
|
className: "text-base",
|
|
242
249
|
children: e.title
|
|
243
250
|
})]
|
|
244
|
-
}), /* @__PURE__ */
|
|
251
|
+
}), /* @__PURE__ */ h(b, {
|
|
245
252
|
className: "pt-0",
|
|
246
253
|
children: [
|
|
247
|
-
/* @__PURE__ */
|
|
254
|
+
/* @__PURE__ */ m("p", {
|
|
248
255
|
className: "text-sm text-text-secondary",
|
|
249
256
|
children: e.content
|
|
250
257
|
}),
|
|
251
|
-
e.tags.length > 0 && /* @__PURE__ */
|
|
258
|
+
e.tags.length > 0 && /* @__PURE__ */ m("div", {
|
|
252
259
|
className: "mt-3 flex flex-wrap gap-1",
|
|
253
|
-
children: e.tags.map((e) => /* @__PURE__ */
|
|
260
|
+
children: e.tags.map((e) => /* @__PURE__ */ m(v, {
|
|
254
261
|
variant: "outline",
|
|
255
262
|
className: "text-[9px]",
|
|
256
263
|
children: e
|
|
257
264
|
}, e))
|
|
258
265
|
}),
|
|
259
|
-
/* @__PURE__ */
|
|
266
|
+
/* @__PURE__ */ h("div", {
|
|
260
267
|
className: "mt-3 flex items-center gap-1 text-xs text-text-muted",
|
|
261
268
|
children: [
|
|
262
|
-
/* @__PURE__ */
|
|
269
|
+
/* @__PURE__ */ m(te, { className: "h-3 w-3" }),
|
|
263
270
|
e.viewCount,
|
|
264
271
|
" read"
|
|
265
272
|
]
|
|
@@ -267,146 +274,146 @@ function I() {
|
|
|
267
274
|
]
|
|
268
275
|
})]
|
|
269
276
|
}, e.id);
|
|
270
|
-
return /* @__PURE__ */
|
|
277
|
+
return /* @__PURE__ */ h("div", {
|
|
271
278
|
className: "space-y-6 p-6",
|
|
272
279
|
children: [
|
|
273
|
-
/* @__PURE__ */
|
|
280
|
+
/* @__PURE__ */ h("div", {
|
|
274
281
|
className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
|
|
275
|
-
children: [/* @__PURE__ */
|
|
276
|
-
/* @__PURE__ */
|
|
282
|
+
children: [/* @__PURE__ */ h("div", { children: [
|
|
283
|
+
/* @__PURE__ */ m("h1", {
|
|
277
284
|
className: "text-2xl font-semibold",
|
|
278
|
-
children: /* @__PURE__ */
|
|
285
|
+
children: /* @__PURE__ */ m(C, { children: "Announcements" })
|
|
279
286
|
}),
|
|
280
|
-
/* @__PURE__ */
|
|
287
|
+
/* @__PURE__ */ h("p", {
|
|
281
288
|
className: "text-sm text-text-secondary",
|
|
282
289
|
children: [O.length, " company announcements"]
|
|
283
290
|
}),
|
|
284
|
-
/* @__PURE__ */
|
|
291
|
+
/* @__PURE__ */ m(E, {
|
|
285
292
|
className: "mt-1",
|
|
286
293
|
children: "Broadcast company-wide news and updates so everyone stays informed — post announcements here when you have something the whole team needs to see."
|
|
287
294
|
})
|
|
288
|
-
] }), /* @__PURE__ */
|
|
295
|
+
] }), /* @__PURE__ */ h(y, {
|
|
289
296
|
size: "sm",
|
|
290
|
-
onClick: () =>
|
|
291
|
-
children: [/* @__PURE__ */
|
|
297
|
+
onClick: () => z.openModal(),
|
|
298
|
+
children: [/* @__PURE__ */ m(l, { className: "h-4 w-4 mr-1" }), "New Announcement"]
|
|
292
299
|
})]
|
|
293
300
|
}),
|
|
294
|
-
/* @__PURE__ */
|
|
301
|
+
/* @__PURE__ */ h("div", {
|
|
295
302
|
className: "relative max-w-md",
|
|
296
|
-
children: [/* @__PURE__ */
|
|
303
|
+
children: [/* @__PURE__ */ m(u, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-text-secondary" }), /* @__PURE__ */ m(T, {
|
|
297
304
|
placeholder: "Search announcements...",
|
|
298
305
|
className: "pl-9",
|
|
299
|
-
value:
|
|
300
|
-
onChange: (e) =>
|
|
306
|
+
value: W,
|
|
307
|
+
onChange: (e) => me(e.target.value)
|
|
301
308
|
})]
|
|
302
309
|
}),
|
|
303
|
-
/* @__PURE__ */
|
|
310
|
+
/* @__PURE__ */ h("div", {
|
|
304
311
|
className: "grid gap-6 lg:grid-cols-3",
|
|
305
|
-
children: [/* @__PURE__ */
|
|
312
|
+
children: [/* @__PURE__ */ h("div", {
|
|
306
313
|
className: "space-y-4 lg:col-span-2",
|
|
307
314
|
children: [
|
|
308
|
-
|
|
315
|
+
J.length === 0 && /* @__PURE__ */ m(w, {
|
|
309
316
|
illustration: "empty-notifications",
|
|
310
|
-
title:
|
|
311
|
-
description:
|
|
317
|
+
title: q ? "No announcements match" : "No announcements yet",
|
|
318
|
+
description: q ? "Try a different search term." : "Post an announcement to share news with the whole team."
|
|
312
319
|
}),
|
|
313
|
-
|
|
320
|
+
Y.length > 0 && /* @__PURE__ */ h("div", {
|
|
314
321
|
className: "space-y-3",
|
|
315
|
-
children: [/* @__PURE__ */
|
|
322
|
+
children: [/* @__PURE__ */ h("h2", {
|
|
316
323
|
className: "flex items-center gap-1 text-sm font-medium",
|
|
317
|
-
children: [/* @__PURE__ */
|
|
318
|
-
}),
|
|
324
|
+
children: [/* @__PURE__ */ m(c, { className: "h-4 w-4" }), "Pinned"]
|
|
325
|
+
}), Y.map((e) => $(e, !0))]
|
|
319
326
|
}),
|
|
320
|
-
|
|
327
|
+
X.length > 0 && /* @__PURE__ */ m("div", {
|
|
321
328
|
className: "space-y-3",
|
|
322
|
-
children:
|
|
329
|
+
children: X.map((e) => $(e, !1))
|
|
323
330
|
})
|
|
324
331
|
]
|
|
325
|
-
}), /* @__PURE__ */
|
|
332
|
+
}), /* @__PURE__ */ m("div", {
|
|
326
333
|
className: "lg:col-span-1",
|
|
327
|
-
children: /* @__PURE__ */
|
|
334
|
+
children: /* @__PURE__ */ h(de, {
|
|
328
335
|
className: "lg:sticky lg:top-6",
|
|
329
|
-
children: [/* @__PURE__ */
|
|
336
|
+
children: [/* @__PURE__ */ h(x, {
|
|
330
337
|
className: "flex flex-row items-center justify-between space-y-0 pb-3",
|
|
331
|
-
children: [/* @__PURE__ */
|
|
338
|
+
children: [/* @__PURE__ */ m(S, {
|
|
332
339
|
className: "text-base",
|
|
333
340
|
children: "Conversations"
|
|
334
|
-
}), /* @__PURE__ */
|
|
341
|
+
}), /* @__PURE__ */ h(y, {
|
|
335
342
|
variant: "ghost",
|
|
336
343
|
size: "sm",
|
|
337
|
-
onClick:
|
|
338
|
-
children: [/* @__PURE__ */
|
|
344
|
+
onClick: Z,
|
|
345
|
+
children: [/* @__PURE__ */ m(ne, { className: "mr-1 h-3.5 w-3.5" }), "Open"]
|
|
339
346
|
})]
|
|
340
|
-
}), /* @__PURE__ */
|
|
347
|
+
}), /* @__PURE__ */ h(b, {
|
|
341
348
|
className: "space-y-1",
|
|
342
|
-
children: [
|
|
349
|
+
children: [K.length === 0 ? /* @__PURE__ */ m("p", {
|
|
343
350
|
className: "py-6 text-center text-xs text-text-muted",
|
|
344
351
|
children: "No active conversations yet. Team channels will appear here as they get activity."
|
|
345
|
-
}) :
|
|
352
|
+
}) : K.map((e) => /* @__PURE__ */ h("button", {
|
|
346
353
|
type: "button",
|
|
347
|
-
onClick:
|
|
354
|
+
onClick: Z,
|
|
348
355
|
className: "flex w-full items-start gap-3 rounded-[var(--radius-card)] p-2 text-left transition-colors hover:bg-bg-sunken",
|
|
349
356
|
children: [
|
|
350
|
-
/* @__PURE__ */
|
|
357
|
+
/* @__PURE__ */ m(r, {
|
|
351
358
|
people: [{ name: e.title }],
|
|
352
359
|
size: 32
|
|
353
360
|
}),
|
|
354
|
-
/* @__PURE__ */
|
|
361
|
+
/* @__PURE__ */ h("div", {
|
|
355
362
|
className: "min-w-0 flex-1",
|
|
356
|
-
children: [/* @__PURE__ */
|
|
363
|
+
children: [/* @__PURE__ */ h("div", {
|
|
357
364
|
className: "flex items-center justify-between gap-2",
|
|
358
|
-
children: [/* @__PURE__ */
|
|
365
|
+
children: [/* @__PURE__ */ m("p", {
|
|
359
366
|
className: "truncate text-sm font-medium",
|
|
360
367
|
children: e.title
|
|
361
|
-
}), /* @__PURE__ */
|
|
368
|
+
}), /* @__PURE__ */ m("span", {
|
|
362
369
|
className: "shrink-0 text-[10px] text-text-muted",
|
|
363
370
|
children: F(e.createdAt)
|
|
364
371
|
})]
|
|
365
|
-
}), /* @__PURE__ */
|
|
372
|
+
}), /* @__PURE__ */ m("p", {
|
|
366
373
|
className: "truncate text-xs text-text-secondary",
|
|
367
374
|
children: e.message
|
|
368
375
|
})]
|
|
369
376
|
}),
|
|
370
|
-
!e.read && /* @__PURE__ */
|
|
377
|
+
!e.read && /* @__PURE__ */ m("span", {
|
|
371
378
|
className: "mt-1.5 h-2 w-2 shrink-0 rounded-full bg-status-success-text",
|
|
372
379
|
"aria-label": "Unread"
|
|
373
380
|
})
|
|
374
381
|
]
|
|
375
|
-
}, e.id)), /* @__PURE__ */
|
|
382
|
+
}, e.id)), /* @__PURE__ */ h(y, {
|
|
376
383
|
variant: "outline",
|
|
377
384
|
size: "sm",
|
|
378
385
|
className: "mt-3 w-full",
|
|
379
|
-
onClick:
|
|
380
|
-
children: [/* @__PURE__ */
|
|
386
|
+
onClick: Z,
|
|
387
|
+
children: [/* @__PURE__ */ m(d, { className: "mr-1 h-3.5 w-3.5" }), "Write a message in Conversations"]
|
|
381
388
|
})]
|
|
382
389
|
})]
|
|
383
390
|
})
|
|
384
391
|
})]
|
|
385
392
|
}),
|
|
386
|
-
/* @__PURE__ */
|
|
387
|
-
open:
|
|
388
|
-
onOpenChange:
|
|
389
|
-
title:
|
|
390
|
-
description:
|
|
391
|
-
fields:
|
|
392
|
-
initialValues:
|
|
393
|
-
submitLabel:
|
|
394
|
-
onSubmit:
|
|
393
|
+
/* @__PURE__ */ m(i, {
|
|
394
|
+
open: z.open,
|
|
395
|
+
onOpenChange: z.onOpenChange,
|
|
396
|
+
title: G ? "Edit Announcement" : "New Announcement",
|
|
397
|
+
description: G ? "Update this announcement for the whole team." : "Share news and updates across the company.",
|
|
398
|
+
fields: G ? P : N,
|
|
399
|
+
initialValues: Q,
|
|
400
|
+
submitLabel: G ? "Save changes" : "Publish",
|
|
401
|
+
onSubmit: he
|
|
395
402
|
}),
|
|
396
|
-
/* @__PURE__ */
|
|
397
|
-
open:
|
|
403
|
+
/* @__PURE__ */ m(g, {
|
|
404
|
+
open: B !== null,
|
|
398
405
|
onOpenChange: (e) => {
|
|
399
|
-
e ||
|
|
406
|
+
e || V(null);
|
|
400
407
|
},
|
|
401
|
-
children: /* @__PURE__ */
|
|
402
|
-
disabled:
|
|
408
|
+
children: /* @__PURE__ */ h(oe, { children: [/* @__PURE__ */ h(le, { children: [/* @__PURE__ */ m(ue, { children: "Delete announcement?" }), /* @__PURE__ */ m(se, { children: B ? `"${B.title}" will be permanently removed. This cannot be undone.` : "" })] }), /* @__PURE__ */ h(ce, { children: [/* @__PURE__ */ m(ae, {
|
|
409
|
+
disabled: H,
|
|
403
410
|
children: "Cancel"
|
|
404
|
-
}), /* @__PURE__ */
|
|
411
|
+
}), /* @__PURE__ */ m(_, {
|
|
405
412
|
onClick: (e) => {
|
|
406
|
-
e.preventDefault(),
|
|
413
|
+
e.preventDefault(), _e();
|
|
407
414
|
},
|
|
408
|
-
disabled:
|
|
409
|
-
children:
|
|
415
|
+
disabled: H,
|
|
416
|
+
children: H ? "Deleting…" : "Delete"
|
|
410
417
|
})] })] })
|
|
411
418
|
})
|
|
412
419
|
]
|