@emberai-engg/task-board 0.3.0 → 0.3.2

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/index.mjs CHANGED
@@ -58,6 +58,11 @@ function createTaskBoardService(apiClient, basePath = "/api/v1/taskboard") {
58
58
  async deleteComment(taskId, commentId) {
59
59
  await apiClient.delete(`${basePath}/tasks/${taskId}/comments/${commentId}`);
60
60
  },
61
+ // ─── Projects ───
62
+ async listProjects() {
63
+ const { data } = await apiClient.get(`${basePath}/projects`);
64
+ return data;
65
+ },
61
66
  // ─── Mentions ───
62
67
  async searchMentionUsers(query) {
63
68
  const { data } = await apiClient.get(
@@ -179,69 +184,25 @@ function TaskBoardProvider({
179
184
  }
180
185
 
181
186
  // src/hooks/useTaskBoard.ts
182
- import { useState, useEffect, useCallback, useMemo as useMemo2, useRef } from "react";
183
-
184
- // src/utils/helpers.ts
185
- function getPriorityStyle(priority) {
186
- return DEFAULT_PRIORITIES.find((p) => p.value === priority) ?? DEFAULT_PRIORITIES[2];
187
- }
188
- function getTagStyle(tag) {
189
- const predefined = PREDEFINED_TAGS.find((t) => t.value === tag);
190
- if (predefined) return predefined;
191
- const label = tag.charAt(0).toUpperCase() + tag.slice(1).replace(/-/g, " ");
192
- return { value: tag, label, className: "bg-neutral-100 text-neutral-500 border-neutral-200" };
193
- }
194
- function getInitials(name) {
195
- return name.split(" ").map((w) => w[0]).join("").toUpperCase().slice(0, 2);
196
- }
197
- function parseDate(dateStr) {
198
- if (!dateStr) return /* @__PURE__ */ new Date();
199
- const d = new Date(dateStr);
200
- if (isNaN(d.getTime()) && !dateStr.endsWith("Z") && !dateStr.includes("+")) {
201
- return /* @__PURE__ */ new Date(dateStr + "Z");
202
- }
203
- return d;
204
- }
205
- function formatDate(dateStr) {
206
- if (!dateStr) return "";
207
- const d = parseDate(dateStr);
208
- return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
209
- }
210
- function formatDateTime(dateStr) {
211
- if (!dateStr) return "";
212
- const d = parseDate(dateStr);
213
- return d.toLocaleDateString("en-US", {
214
- month: "short",
215
- day: "numeric",
216
- hour: "numeric",
217
- minute: "2-digit"
218
- });
219
- }
220
- function getDescriptionPreview(desc) {
221
- if (!desc) return "";
222
- if (typeof desc === "string") return desc;
223
- for (const section of DESCRIPTION_SECTIONS) {
224
- if (desc[section.key]?.trim()) return desc[section.key].trim();
225
- }
226
- return "";
227
- }
228
- function hasDescription(desc) {
229
- if (!desc) return false;
230
- if (typeof desc === "string") return desc.trim().length > 0;
231
- return DESCRIPTION_SECTIONS.some((s) => desc[s.key]?.trim());
232
- }
233
- function getUserProjects(apps, allProjects) {
234
- if (apps.includes("all")) return allProjects;
235
- return allProjects.filter((p) => apps.includes(p.slug));
236
- }
237
-
238
- // src/hooks/useTaskBoard.ts
187
+ import { useState, useEffect, useCallback, useRef } from "react";
239
188
  function useTaskBoard() {
240
189
  const { service, user, projects: configProjects, columns, config } = useTaskBoardContext();
241
- const projects = useMemo2(
242
- () => configProjects.length > 0 ? configProjects : getUserProjects(user.apps, []),
243
- [configProjects, user.apps]
244
- );
190
+ const [fetchedProjects, setFetchedProjects] = useState([]);
191
+ useEffect(() => {
192
+ if (configProjects.length > 0) return;
193
+ let cancelled = false;
194
+ (async () => {
195
+ try {
196
+ const data = await service.listProjects();
197
+ if (!cancelled) setFetchedProjects(data);
198
+ } catch {
199
+ }
200
+ })();
201
+ return () => {
202
+ cancelled = true;
203
+ };
204
+ }, [configProjects, service]);
205
+ const projects = configProjects.length > 0 ? configProjects : fetchedProjects;
245
206
  const [selectedProject, setSelectedProject] = useState("");
246
207
  const [tasks, setTasks] = useState({});
247
208
  const [columnTotals, setColumnTotals] = useState({});
@@ -464,6 +425,60 @@ import { Droppable } from "@hello-pangea/dnd";
464
425
  import { memo } from "react";
465
426
  import { Draggable } from "@hello-pangea/dnd";
466
427
 
428
+ // src/utils/helpers.ts
429
+ function getPriorityStyle(priority) {
430
+ return DEFAULT_PRIORITIES.find((p) => p.value === priority) ?? DEFAULT_PRIORITIES[2];
431
+ }
432
+ function getTagStyle(tag) {
433
+ const predefined = PREDEFINED_TAGS.find((t) => t.value === tag);
434
+ if (predefined) return predefined;
435
+ const label = tag.charAt(0).toUpperCase() + tag.slice(1).replace(/-/g, " ");
436
+ return { value: tag, label, className: "bg-neutral-100 text-neutral-500 border-neutral-200" };
437
+ }
438
+ function getInitials(name) {
439
+ return name.split(" ").map((w) => w[0]).join("").toUpperCase().slice(0, 2);
440
+ }
441
+ function parseDate(dateStr) {
442
+ if (!dateStr) return /* @__PURE__ */ new Date();
443
+ const d = new Date(dateStr);
444
+ if (isNaN(d.getTime()) && !dateStr.endsWith("Z") && !dateStr.includes("+")) {
445
+ return /* @__PURE__ */ new Date(dateStr + "Z");
446
+ }
447
+ return d;
448
+ }
449
+ function formatDate(dateStr) {
450
+ if (!dateStr) return "";
451
+ const d = parseDate(dateStr);
452
+ return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
453
+ }
454
+ function formatDateTime(dateStr) {
455
+ if (!dateStr) return "";
456
+ const d = parseDate(dateStr);
457
+ return d.toLocaleDateString("en-US", {
458
+ month: "short",
459
+ day: "numeric",
460
+ hour: "numeric",
461
+ minute: "2-digit"
462
+ });
463
+ }
464
+ function getDescriptionPreview(desc) {
465
+ if (!desc) return "";
466
+ if (typeof desc === "string") return desc;
467
+ for (const section of DESCRIPTION_SECTIONS) {
468
+ if (desc[section.key]?.trim()) return desc[section.key].trim();
469
+ }
470
+ return "";
471
+ }
472
+ function hasDescription(desc) {
473
+ if (!desc) return false;
474
+ if (typeof desc === "string") return desc.trim().length > 0;
475
+ return DESCRIPTION_SECTIONS.some((s) => desc[s.key]?.trim());
476
+ }
477
+ function getUserProjects(apps, allProjects) {
478
+ if (apps.includes("all")) return allProjects;
479
+ return allProjects.filter((p) => apps.includes(p.slug));
480
+ }
481
+
467
482
  // src/components/PriorityBadge.tsx
468
483
  import { jsx as jsx3 } from "react/jsx-runtime";
469
484
  function PriorityBadge({ priority, size = "sm" }) {