@lv-x-software-house/x_view 1.3.0-dev.1 → 1.3.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.
Files changed (3) hide show
  1. package/dist/index.js +378 -163
  2. package/dist/index.mjs +379 -164
  3. package/package.json +4 -2
package/dist/index.mjs CHANGED
@@ -2268,7 +2268,7 @@ var userActionHandlers = {
2268
2268
  }
2269
2269
  },
2270
2270
  handleSaveNodeDetails: async (context, updatedNode, keepOpen = false) => {
2271
- var _a, _b, _c, _d;
2271
+ var _a, _b, _c, _d, _e, _f;
2272
2272
  const { graphDataRef, sceneDataRef, stateRef, setters } = context;
2273
2273
  if (!graphDataRef.current || !sceneDataRef.current) return;
2274
2274
  const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
@@ -2317,35 +2317,41 @@ var userActionHandlers = {
2317
2317
  const isNewDone = oldNode.status !== "Done" && nodeToSave.status === "Done";
2318
2318
  specificParentData.nodes[nodeIndex] = { ...nodeToSave };
2319
2319
  if (isNewDone && nodeToSave.is_quest && ((_b = nodeToSave.recurrence_config) == null ? void 0 : _b.enabled)) {
2320
+ const rootId = ((_c = nodeToSave.version_node) == null ? void 0 : _c.parent_node) || nodeToSave.id;
2321
+ const rootNode = specificParentData.nodes.find((n) => String(n.id) === String(rootId)) || nodeToSave;
2320
2322
  const nextDateObj = calculateNextRecurrenceDate(
2321
- nodeToSave.recurrence_config
2323
+ ((_d = rootNode.recurrence_config) == null ? void 0 : _d.enabled) ? rootNode.recurrence_config : nodeToSave.recurrence_config
2322
2324
  );
2323
2325
  if (nextDateObj) {
2324
2326
  const currentCounter = sceneDataRef.current.quest_counter || 1;
2325
2327
  const usedCounter = currentCounter;
2326
2328
  const nextCounter = currentCounter + 1;
2327
2329
  sceneDataRef.current.quest_counter = nextCounter;
2328
- let nextName = nodeToSave.raw_title || nodeToSave.name;
2329
- const prefixParts = (nodeToSave.name || "").split(" - \xBB ");
2330
+ let nextName = rootNode.raw_title || rootNode.name;
2331
+ const prefixParts = (rootNode.name || "").split(" - \xBB ");
2330
2332
  const questPrefix = prefixParts.length > 1 ? prefixParts[0] : "";
2331
2333
  if (questPrefix) {
2332
2334
  const baseParts = questPrefix.split(" - ");
2333
2335
  const prefixBase = baseParts[0];
2334
- nextName = `${prefixBase} - ${usedCounter} - \xBB ${nodeToSave.raw_title || prefixParts[1]}`;
2336
+ nextName = `${prefixBase} - ${usedCounter} - \xBB ${rootNode.raw_title || prefixParts[1]}`;
2335
2337
  } else {
2336
- nextName = `${usedCounter} - \xBB ${nodeToSave.raw_title || nodeToSave.name}`;
2338
+ nextName = `${usedCounter} - \xBB ${rootNode.raw_title || rootNode.name}`;
2337
2339
  }
2338
- const nextRecurrenceConfig = { ...nodeToSave.recurrence_config };
2340
+ const nextRecurrenceConfig = {
2341
+ ...rootNode.recurrence_config || nodeToSave.recurrence_config
2342
+ };
2339
2343
  if (nextRecurrenceConfig.type === "custom") {
2340
2344
  nextRecurrenceConfig.custom_date = "";
2341
2345
  }
2342
2346
  const nextQuestNode = {
2343
- ...JSON.parse(JSON.stringify(nodeToSave)),
2347
+ ...JSON.parse(JSON.stringify(rootNode)),
2348
+ // HERANÇA DO ROOT (Template)
2344
2349
  id: short.generate(),
2345
2350
  name: nextName,
2346
2351
  status: "Backlog",
2347
2352
  color: "#64748b",
2348
- assignee_id: nodeToSave.recurrence_config.next_assignee_id || "",
2353
+ // ATRIBUIÇÃO LOCAL: Respeita a escolha feita no momento da conclusão da atual
2354
+ assignee_id: ((_e = nodeToSave.recurrence_config) == null ? void 0 : _e.next_assignee_id) || "",
2349
2355
  Date: nextDateObj,
2350
2356
  timeline: [
2351
2357
  {
@@ -2361,15 +2367,47 @@ var userActionHandlers = {
2361
2367
  ],
2362
2368
  version_node: {
2363
2369
  is_version: true,
2364
- parent_node: ((_c = nodeToSave.version_node) == null ? void 0 : _c.parent_node) || nodeToSave.id
2370
+ parent_node: rootId
2365
2371
  },
2366
- reviewStack: (nodeToSave.reviewStack || []).map((r) => ({
2372
+ reviewStack: (rootNode.reviewStack || []).map((r) => ({
2367
2373
  ...r,
2368
2374
  status: "pending"
2369
2375
  })),
2370
2376
  recurrence_config: nextRecurrenceConfig
2371
2377
  };
2372
- const rootId = ((_d = nodeToSave.version_node) == null ? void 0 : _d.parent_node) || nodeToSave.id;
2378
+ if (context.actions.copy_google_doc_action && nextQuestNode.Links) {
2379
+ const links = nextQuestNode.Links;
2380
+ const docLinkIndex = links.findIndex((l) => l.name === "Google docs");
2381
+ if (docLinkIndex !== -1) {
2382
+ const originalUrl = links[docLinkIndex].value;
2383
+ if (originalUrl) {
2384
+ const docIdMatch = originalUrl.match(/\/d\/([a-zA-Z0-9-_]+)/);
2385
+ if (docIdMatch && docIdMatch[1]) {
2386
+ const fileId = docIdMatch[1];
2387
+ const viewFolderId = (_f = sceneDataRef.current) == null ? void 0 : _f.view_google_folder_id;
2388
+ try {
2389
+ const copyRes = await context.actions.copy_google_doc_action(
2390
+ fileId,
2391
+ nextName,
2392
+ viewFolderId
2393
+ );
2394
+ if (copyRes.success && copyRes.link) {
2395
+ nextQuestNode.Links[docLinkIndex].value = copyRes.link;
2396
+ nextQuestNode.timeline.push({
2397
+ id: short.generate(),
2398
+ type: "system_note",
2399
+ timestamp: Date.now(),
2400
+ actorId: "system",
2401
+ description: `Documento Google Docs clonado individualmente para esta inst\xE2ncia.`
2402
+ });
2403
+ }
2404
+ } catch (copyErr) {
2405
+ console.warn("Falha ao clonar Google Doc para recorr\xEAncia:", copyErr);
2406
+ }
2407
+ }
2408
+ }
2409
+ }
2410
+ }
2373
2411
  const nextQuestLink = {
2374
2412
  id: `link_${short.generate()}`,
2375
2413
  source: rootId,
@@ -2600,6 +2638,13 @@ var MENTION_REGEX = /\[\[MENTION:node:([a-zA-Z0-9\-_]+)\]\]/g;
2600
2638
  var IMAGE_MENTION_REGEX = /\[\[MENTION:image:([^|\]]+)\|?([^\]]*)\]\]/g;
2601
2639
  var LINK_REGEX = /\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/g;
2602
2640
  var UNIQUE_PROP_TYPES = ["links", "images", "date", "documents"];
2641
+ var QUEST_STATUS_COLORS = {
2642
+ Backlog: "#64748b",
2643
+ "In Progress": "#eab308",
2644
+ Review: "#a855f7",
2645
+ Done: "#22c55e"
2646
+ };
2647
+ var QUEST_STATUSES = ["Backlog", "In Progress", "Review", "Done"];
2603
2648
  function createNewCustomProperty(existingProps = []) {
2604
2649
  const usedTypes = new Set(existingProps.map((p) => p.type));
2605
2650
  let nextType = "text";
@@ -2878,7 +2923,8 @@ var IGNORED_KEYS = [
2878
2923
  "milestone_ids",
2879
2924
  "dependency_ids",
2880
2925
  "quest_tree",
2881
- "quest_abstraction_tree"
2926
+ "quest_abstraction_tree",
2927
+ "assignees"
2882
2928
  ];
2883
2929
  function extractCustomPropsFromNode(node) {
2884
2930
  const customPropTypes = node._customPropTypes || {};
@@ -3507,16 +3553,14 @@ function checkCircularDependency(targetId, depIdToAdd, allNodes = []) {
3507
3553
  };
3508
3554
  return hasPath(depIdToAdd, targetId);
3509
3555
  }
3556
+ function checkAllAssigneesDone(assignees) {
3557
+ if (!assignees || !Array.isArray(assignees) || assignees.length === 0)
3558
+ return true;
3559
+ return assignees.every((a) => a.status === "done");
3560
+ }
3510
3561
 
3511
3562
  // src/components/ContextMenu.jsx
3512
3563
  import { FiLock, FiChevronRight } from "react-icons/fi";
3513
- var QUEST_STATUS_COLORS = {
3514
- "Backlog": "#64748b",
3515
- "In Progress": "#eab308",
3516
- "Review": "#a855f7",
3517
- "Done": "#22c55e"
3518
- };
3519
- var QUEST_STATUSES = ["Backlog", "In Progress", "Review", "Done"];
3520
3564
  function ContextMenu({
3521
3565
  data,
3522
3566
  userRole,
@@ -3752,15 +3796,17 @@ function ContextMenu({
3752
3796
  });
3753
3797
  };
3754
3798
  const renderMainView = () => {
3755
- var _a2, _b2, _c, _d, _e, _f, _g, _h;
3799
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
3756
3800
  const hasVersions = computedVersions.length > 0;
3757
3801
  const canCreateVersion = ability.can("create", "Versioning");
3758
3802
  const canReadVersion = ability.can("read", "Versioning");
3759
3803
  const shouldShowVersioningBtn = canCreateVersion || canReadVersion && hasVersions;
3760
- const canStartQuest = isCurrentNodeQuest && (((_a2 = data.nodeData) == null ? void 0 : _a2.status) === "Backlog" || !((_b2 = data.nodeData) == null ? void 0 : _b2.status));
3761
- const isQuestActuallyBlocked = canStartQuest && blockedStatus.isBlocked;
3762
- const canFinishQuest = isCurrentNodeQuest && ((_c = data.nodeData) == null ? void 0 : _c.assignee_id) === (currentUser == null ? void 0 : currentUser.id) && ((_d = data.nodeData) == null ? void 0 : _d.status) !== "Backlog" && ((_e = data.nodeData) == null ? void 0 : _e.status) !== "Done";
3763
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ React.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es R\xE1pidas")), /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-1" }, canStartQuest && /* @__PURE__ */ React.createElement(
3804
+ const isUserAssignee = ((_b2 = (_a2 = data.nodeData) == null ? void 0 : _a2.assignees) == null ? void 0 : _b2.some((a) => String(a.id) === String(currentUser == null ? void 0 : currentUser.id))) || !((_c = data.nodeData) == null ? void 0 : _c.assignees) && String((_d = data.nodeData) == null ? void 0 : _d.assignee_id) === String(currentUser == null ? void 0 : currentUser.id);
3805
+ const canStartQuest = isCurrentNodeQuest && (((_e = data.nodeData) == null ? void 0 : _e.status) === "Backlog" || !((_f = data.nodeData) == null ? void 0 : _f.status));
3806
+ const canJoinQuest = isCurrentNodeQuest && ((_g = data.nodeData) == null ? void 0 : _g.status) === "In Progress" && !isUserAssignee;
3807
+ const isQuestActuallyBlocked = (canStartQuest || canJoinQuest) && blockedStatus.isBlocked;
3808
+ const canFinishQuest = isCurrentNodeQuest && isUserAssignee && ((_h = data.nodeData) == null ? void 0 : _h.status) === "In Progress" && ((_k = (_j = (_i = data.nodeData) == null ? void 0 : _i.assignees) == null ? void 0 : _j.find((a) => String(a.id) === String(currentUser == null ? void 0 : currentUser.id))) == null ? void 0 : _k.status) !== "done";
3809
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ React.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es R\xE1pidas")), /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-1" }, (canStartQuest || canJoinQuest) && /* @__PURE__ */ React.createElement(
3764
3810
  "button",
3765
3811
  {
3766
3812
  onClick: () => {
@@ -3771,10 +3817,10 @@ function ContextMenu({
3771
3817
  },
3772
3818
  disabled: isQuestActuallyBlocked,
3773
3819
  className: `${baseButtonClass} ${isQuestActuallyBlocked ? "opacity-50 grayscale cursor-not-allowed group" : ""}`,
3774
- title: isQuestActuallyBlocked ? "Bloqueado por pr\xE9-requisitos pendentes" : "Atribuir a mim e iniciar"
3820
+ title: isQuestActuallyBlocked ? "Bloqueado por pr\xE9-requisitos pendentes" : canJoinQuest ? "Entrar como respons\xE1vel" : "Atribuir a mim e iniciar"
3775
3821
  },
3776
3822
  isQuestActuallyBlocked ? /* @__PURE__ */ React.createElement(FiLock, { size: 16, className: "text-amber-400/80" }) : /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z" }), /* @__PURE__ */ React.createElement("path", { d: "m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z" }), /* @__PURE__ */ React.createElement("path", { d: "M9 12H4s.55-3.03 2-5c1.62-2.2 5-4 5-4" }), /* @__PURE__ */ React.createElement("path", { d: "M12 15v5s3.03-.55 5-2c2.2-1.62 4-5 4-5" })),
3777
- /* @__PURE__ */ React.createElement("span", { className: isQuestActuallyBlocked ? "text-amber-200/60" : "" }, "Iniciar Quest"),
3823
+ /* @__PURE__ */ React.createElement("span", { className: isQuestActuallyBlocked ? "text-amber-200/60" : "" }, canJoinQuest ? "Entrar na Quest" : "Iniciar Quest"),
3778
3824
  isQuestActuallyBlocked && /* @__PURE__ */ React.createElement(FiLock, { className: "ml-auto opacity-0 group-hover:opacity-100 transition-opacity", size: 12 })
3779
3825
  ), canFinishQuest && /* @__PURE__ */ React.createElement(
3780
3826
  "button",
@@ -3788,7 +3834,7 @@ function ContextMenu({
3788
3834
  },
3789
3835
  /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M22 11.08V12a10 10 0 1 1-5.93-9.14" }), /* @__PURE__ */ React.createElement("polyline", { points: "22 4 12 14.01 9 11.01" })),
3790
3836
  /* @__PURE__ */ React.createElement("span", null, "Finalizar Etapa")
3791
- ), (canStartQuest || canFinishQuest) && /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), isCurrentNodeQuest && ((_g = (_f = data.nodeData) == null ? void 0 : _f.dependency_ids) == null ? void 0 : _g.length) > 0 && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-1.5" }, /* @__PURE__ */ React.createElement("span", { className: "text-[10px] uppercase tracking-wider text-slate-500 font-bold" }, "Prerrequisitos")), /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-0.5 px-1 pb-1" }, data.nodeData.dependency_ids.map((depId) => {
3837
+ ), (canStartQuest || canJoinQuest || canFinishQuest) && /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), isCurrentNodeQuest && ((_m = (_l = data.nodeData) == null ? void 0 : _l.dependency_ids) == null ? void 0 : _m.length) > 0 && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-1.5" }, /* @__PURE__ */ React.createElement("span", { className: "text-[10px] uppercase tracking-wider text-slate-500 font-bold" }, "Prerrequisitos")), /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-0.5 px-1 pb-1" }, data.nodeData.dependency_ids.map((depId) => {
3792
3838
  const depNode = allParentNodes.find((n) => String(n.id) === String(depId));
3793
3839
  if (!depNode) return null;
3794
3840
  const isPrereqDone = depNode.status === "Done";
@@ -3806,7 +3852,7 @@ function ContextMenu({
3806
3852
  /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ React.createElement("div", { className: `w-1.5 h-1.5 rounded-full flex-shrink-0 ${isPrereqDone ? "bg-green-500" : "bg-amber-500 animate-pulse"}` }), /* @__PURE__ */ React.createElement("span", { className: `truncate ${isPrereqDone ? "text-slate-400" : "text-slate-200 font-medium"}` }, depNode.raw_title || depNode.name)),
3807
3853
  /* @__PURE__ */ React.createElement(FiChevronRight, { className: "opacity-0 group-hover:opacity-100 transition-opacity text-slate-500", size: 12 })
3808
3854
  );
3809
- })), /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" })), ability.can("create", "Connection") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartConnection == null ? void 0 : onStartConnection(data.nodeData), className: baseButtonClass, title: "Conectar" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }), /* @__PURE__ */ React.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })), /* @__PURE__ */ React.createElement("span", null, "Conectar")), ability.can("create", "Node") && !((_h = data.nodeData) == null ? void 0 : _h.is_quest) && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartCreation == null ? void 0 : onStartCreation(data.nodeData), className: baseButtonClass, title: "Criar e Conectar" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "16" }), /* @__PURE__ */ React.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" })), /* @__PURE__ */ React.createElement("span", null, "Criar e Conectar")), ability.can("create", "Ancestry") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartAncestryCreation == null ? void 0 : onStartAncestryCreation(data.nodeData), className: baseButtonClass, title: "Criar Ancestralidade" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M10 20.5c.5-.5.8-1.2.8-2s-.3-1.5-.8-2c-.5-.5-1.2-.8-2-.8s-1.5.3-2 .8c-.5.5-.8 1.2-.8 2s.3 1.5.8 2c.5.5 1.2-.8 2 .8s1.5-.3 2-.8c-.5-.5-.8-1.2-.8-2s.3-1.5.8-2c.5.5 1.2-.8 2 .8s1.5.3 2 .8Z" }), /* @__PURE__ */ React.createElement("path", { d: "M10 16v-3a2 2 0 0 1 2-2h4" }), /* @__PURE__ */ React.createElement("path", { d: "M14 3.5c.5.5.8 1.2.8 2s-.3 1.5-.8 2c-.5-.5-1.2-.8-2 .8s1.5.3-2-.8c-.5-.5-.8-1.2-.8-2s.3-1.5.8-2c.5.5 1.2-.8 2 .8s1.5.3 2 .8Z" }), /* @__PURE__ */ React.createElement("path", { d: "M14 8v3a2 2 0 0 0 2 2h4" })), /* @__PURE__ */ React.createElement("span", null, "Criar Ancestralidade")), shouldShowVersioningBtn && /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("versioning"), className: baseButtonClass, title: hasVersions ? "Versionamento" : "Criar Versionamento" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("line", { x1: "6", y1: "3", x2: "6", y2: "15" }), /* @__PURE__ */ React.createElement("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ React.createElement("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ React.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })), /* @__PURE__ */ React.createElement("span", null, hasVersions || !canCreateVersion ? "Versionamento" : "Criar Versionamento")), (connections.length > 0 || availableAncestries.length > 0) && ability.can("read", "Connection") && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("connections"), className: baseButtonClass, title: "Conex\xF5es" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2z" }), /* @__PURE__ */ React.createElement("path", { d: "M8 12h8" }), /* @__PURE__ */ React.createElement("path", { d: "M12 8v8" })), /* @__PURE__ */ React.createElement("span", null, "Conex\xF5es (", totalConnectionsCount, ")"))), /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React.createElement("button", { onClick: () => {
3855
+ })), /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" })), ability.can("create", "Connection") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartConnection == null ? void 0 : onStartConnection(data.nodeData), className: baseButtonClass, title: "Conectar" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }), /* @__PURE__ */ React.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })), /* @__PURE__ */ React.createElement("span", null, "Conectar")), ability.can("create", "Node") && !((_n = data.nodeData) == null ? void 0 : _n.is_quest) && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartCreation == null ? void 0 : onStartCreation(data.nodeData), className: baseButtonClass, title: "Criar e Conectar" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "16" }), /* @__PURE__ */ React.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" })), /* @__PURE__ */ React.createElement("span", null, "Criar e Conectar")), ability.can("create", "Ancestry") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartAncestryCreation == null ? void 0 : onStartAncestryCreation(data.nodeData), className: baseButtonClass, title: "Criar Ancestralidade" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M10 20.5c.5-.5.8-1.2.8-2s-.3-1.5-.8-2c-.5-.5-1.2-.8-2-.8s-1.5.3-2 .8c-.5.5-.8 1.2-.8 2s.3 1.5.8 2c.5.5 1.2-.8 2 .8s1.5-.3 2-.8c-.5-.5-.8-1.2-.8-2s.3-1.5.8-2c.5.5 1.2-.8 2 .8s1.5.3 2 .8Z" }), /* @__PURE__ */ React.createElement("path", { d: "M10 16v-3a2 2 0 0 1 2-2h4" }), /* @__PURE__ */ React.createElement("path", { d: "M14 3.5c.5.5.8 1.2.8 2s-.3 1.5-.8 2c-.5-.5-1.2-.8-2 .8s1.5.3-2-.8c-.5-.5-.8-1.2-.8-2s.3-1.5.8-2c.5.5 1.2-.8 2 .8s1.5.3 2 .8Z" }), /* @__PURE__ */ React.createElement("path", { d: "M14 8v3a2 2 0 0 0 2 2h4" })), /* @__PURE__ */ React.createElement("span", null, "Criar Ancestralidade")), shouldShowVersioningBtn && /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("versioning"), className: baseButtonClass, title: hasVersions ? "Versionamento" : "Criar Versionamento" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("line", { x1: "6", y1: "3", x2: "6", y2: "15" }), /* @__PURE__ */ React.createElement("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ React.createElement("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ React.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })), /* @__PURE__ */ React.createElement("span", null, hasVersions || !canCreateVersion ? "Versionamento" : "Criar Versionamento")), (connections.length > 0 || availableAncestries.length > 0) && ability.can("read", "Connection") && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("connections"), className: baseButtonClass, title: "Conex\xF5es" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2z" }), /* @__PURE__ */ React.createElement("path", { d: "M8 12h8" }), /* @__PURE__ */ React.createElement("path", { d: "M12 8v8" })), /* @__PURE__ */ React.createElement("span", null, "Conex\xF5es (", totalConnectionsCount, ")"))), /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React.createElement("button", { onClick: () => {
3810
3856
  onFocusNode == null ? void 0 : onFocusNode(data.nodeData);
3811
3857
  onClose();
3812
3858
  }, className: baseButtonClass, title: "Focar na c\xE2mera" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "3" })), /* @__PURE__ */ React.createElement("span", null, "Focar neste Node")), /* @__PURE__ */ React.createElement("button", { onClick: (e) => handleCopyLink(e, data.nodeData), className: baseButtonClass, title: "Copiar Link para Compartilhar" }, isLinkCopied ? /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#4ade80", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("polyline", { points: "20 6 9 17 4 12" })) : /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }), /* @__PURE__ */ React.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })), /* @__PURE__ */ React.createElement("span", { className: isLinkCopied ? "text-green-400" : "" }, isLinkCopied ? "Copiado!" : "Copiar Link")), ability.can("dismiss", "Node") && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("button", { onClick: () => onDismissNode == null ? void 0 : onDismissNode(data.nodeData), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ React.createElement("path", { d: "M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" }), /* @__PURE__ */ React.createElement("path", { d: "M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" }), /* @__PURE__ */ React.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ React.createElement("span", null, "Dismiss")), /* @__PURE__ */ React.createElement("button", { onClick: () => onDismissOtherNodes == null ? void 0 : onDismissOtherNodes(data.nodeData), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ React.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ React.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ React.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ React.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ React.createElement("span", null, "Dismiss other nodes"))), ability.can("delete", "Node") && /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("deleteConfirmation"), className: deleteButtonClass, title: "Excluir Node" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ React.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ React.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ React.createElement("span", null, "Excluir Node"))));
@@ -4614,6 +4660,7 @@ function XViewSidebar({
4614
4660
  status: questFilterStatus,
4615
4661
  milestoneId: questFilterMilestone
4616
4662
  });
4663
+ onToggle(false);
4617
4664
  } finally {
4618
4665
  setIsQuestLensLoading(false);
4619
4666
  }
@@ -4678,6 +4725,7 @@ function XViewSidebar({
4678
4725
  centerNodeId: reshapeCenterNodeId
4679
4726
  });
4680
4727
  setActiveSubMenu(null);
4728
+ onToggle(false);
4681
4729
  },
4682
4730
  disabled: reshapeLayoutType === "Star" && !reshapeCenterNodeId,
4683
4731
  className: "flex-[2] py-3 bg-indigo-600 hover:bg-indigo-500 text-white text-[10px] font-black uppercase tracking-widest rounded-xl shadow-lg shadow-indigo-500/20 transition-all hover:scale-[1.02] active:scale-95 disabled:opacity-30 disabled:grayscale disabled:cursor-not-allowed"
@@ -4933,22 +4981,33 @@ function XViewSidebar({
4933
4981
  /* @__PURE__ */ React2.createElement("polyline", { points: "2 12 12 17 22 12" })
4934
4982
  ),
4935
4983
  "Reshape"
4936
- )), /* @__PURE__ */ React2.createElement("button", { onClick: onActivateTimeline, className: buttonBaseClass }, /* @__PURE__ */ React2.createElement(
4937
- "svg",
4984
+ )), /* @__PURE__ */ React2.createElement(
4985
+ "button",
4938
4986
  {
4939
- xmlns: "http://www.w3.org/2000/svg",
4940
- width: "16",
4941
- height: "16",
4942
- viewBox: "0 0 24 24",
4943
- fill: "none",
4944
- stroke: "currentColor",
4945
- strokeWidth: "2",
4946
- strokeLinecap: "round",
4947
- strokeLinejoin: "round"
4987
+ onClick: () => {
4988
+ onActivateTimeline();
4989
+ onToggle(false);
4990
+ },
4991
+ className: buttonBaseClass
4948
4992
  },
4949
- /* @__PURE__ */ React2.createElement("circle", { cx: "12", cy: "12", r: "10" }),
4950
- /* @__PURE__ */ React2.createElement("polyline", { points: "12 6 12 12 16 14" })
4951
- ), "Timeline"), /* @__PURE__ */ React2.createElement("button", { onClick: onOpenBoards, className: buttonBaseClass }, /* @__PURE__ */ React2.createElement(FiLayers, { size: 16 }), "Boards")), /* @__PURE__ */ React2.createElement("div", { className: "h-px bg-white/10" }), /* @__PURE__ */ React2.createElement("section", { className: "space-y-3" }, /* @__PURE__ */ React2.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Milestones"), /* @__PURE__ */ React2.createElement(
4993
+ /* @__PURE__ */ React2.createElement(
4994
+ "svg",
4995
+ {
4996
+ xmlns: "http://www.w3.org/2000/svg",
4997
+ width: "16",
4998
+ height: "16",
4999
+ viewBox: "0 0 24 24",
5000
+ fill: "none",
5001
+ stroke: "currentColor",
5002
+ strokeWidth: "2",
5003
+ strokeLinecap: "round",
5004
+ strokeLinejoin: "round"
5005
+ },
5006
+ /* @__PURE__ */ React2.createElement("circle", { cx: "12", cy: "12", r: "10" }),
5007
+ /* @__PURE__ */ React2.createElement("polyline", { points: "12 6 12 12 16 14" })
5008
+ ),
5009
+ "Timeline"
5010
+ ), /* @__PURE__ */ React2.createElement("button", { onClick: onOpenBoards, className: buttonBaseClass }, /* @__PURE__ */ React2.createElement(FiLayers, { size: 16 }), "Boards")), /* @__PURE__ */ React2.createElement("div", { className: "h-px bg-white/10" }), /* @__PURE__ */ React2.createElement("section", { className: "space-y-3" }, /* @__PURE__ */ React2.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Milestones"), /* @__PURE__ */ React2.createElement(
4952
5011
  "button",
4953
5012
  {
4954
5013
  onClick: onOpenMilestoneManager,
@@ -6511,6 +6570,7 @@ function DescriptionDisplay({
6511
6570
  mentionCount++;
6512
6571
  }
6513
6572
  });
6573
+ console.log("[DescriptionDisplay] flatNavigation computed:", navItems.length, "items", navItems);
6514
6574
  return navItems;
6515
6575
  }, [sections]);
6516
6576
  const [currentStepIndex, setCurrentStepIndex] = useState7(0);
@@ -6557,14 +6617,24 @@ function DescriptionDisplay({
6557
6617
  const handleKeyDown = (e) => {
6558
6618
  if (e.target.tagName === "INPUT" || e.target.tagName === "TEXTAREA") return;
6559
6619
  const currentItem = flatNavigation[currentStepIndex];
6620
+ if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)) {
6621
+ console.log(`[DescriptionDisplay] Key pressed: ${e.key}`, {
6622
+ currentStepIndex,
6623
+ flatNavigationLength: flatNavigation.length,
6624
+ currentItem,
6625
+ currentBranchDirection
6626
+ });
6627
+ }
6560
6628
  if (e.key === "ArrowRight") {
6561
6629
  e.preventDefault();
6562
6630
  e.stopPropagation();
6563
6631
  if (currentStepIndex === 0 && currentBranchDirection === "left") {
6632
+ console.log("[DescriptionDisplay] ArrowRight: Navigating back from left branch");
6564
6633
  if (onBranchNav) onBranchNav(null, "back");
6565
6634
  return;
6566
6635
  }
6567
6636
  if (currentItem && currentItem.type === "mention" && onBranchNav) {
6637
+ console.log("[DescriptionDisplay] ArrowRight: Opening right branch for node", currentItem.nodeId);
6568
6638
  onBranchNav(currentItem.nodeId, "open", "right");
6569
6639
  return;
6570
6640
  }
@@ -6573,10 +6643,12 @@ function DescriptionDisplay({
6573
6643
  e.preventDefault();
6574
6644
  e.stopPropagation();
6575
6645
  if (currentStepIndex === 0 && currentBranchDirection === "right") {
6646
+ console.log("[DescriptionDisplay] ArrowLeft: Navigating back from right branch");
6576
6647
  if (onBranchNav) onBranchNav(null, "back");
6577
6648
  return;
6578
6649
  }
6579
6650
  if (currentItem && currentItem.type === "mention" && onBranchNav) {
6651
+ console.log("[DescriptionDisplay] ArrowLeft: Opening left branch for node", currentItem.nodeId);
6580
6652
  onBranchNav(currentItem.nodeId, "open", "left");
6581
6653
  return;
6582
6654
  }
@@ -6584,18 +6656,33 @@ function DescriptionDisplay({
6584
6656
  if (e.key === "ArrowDown") {
6585
6657
  e.preventDefault();
6586
6658
  if (flatNavigation.length > 1) {
6587
- setCurrentStepIndex((prev) => Math.min(prev + 1, flatNavigation.length - 1));
6659
+ setCurrentStepIndex((prev) => {
6660
+ const next = Math.min(prev + 1, flatNavigation.length - 1);
6661
+ console.log(`[DescriptionDisplay] ArrowDown: ${prev} -> ${next}`);
6662
+ return next;
6663
+ });
6588
6664
  }
6589
6665
  }
6590
6666
  if (e.key === "ArrowUp") {
6591
6667
  e.preventDefault();
6592
6668
  if (flatNavigation.length > 1) {
6593
- setCurrentStepIndex((prev) => Math.max(prev - 1, 0));
6669
+ setCurrentStepIndex((prev) => {
6670
+ const next = Math.max(prev - 1, 0);
6671
+ console.log(`[DescriptionDisplay] ArrowUp: ${prev} -> ${next}`);
6672
+ return next;
6673
+ });
6594
6674
  }
6595
6675
  }
6596
6676
  };
6677
+ console.log("[DescriptionDisplay] Attaching keydown listener", {
6678
+ flatNavigationLength: flatNavigation.length,
6679
+ currentStepIndex,
6680
+ currentBranchDirection
6681
+ });
6597
6682
  window.addEventListener("keydown", handleKeyDown);
6598
- return () => window.removeEventListener("keydown", handleKeyDown);
6683
+ return () => {
6684
+ window.removeEventListener("keydown", handleKeyDown);
6685
+ };
6599
6686
  }, [flatNavigation, currentStepIndex, onBranchNav, currentBranchDirection]);
6600
6687
  useEffect6(() => {
6601
6688
  if (activeRef.current) {
@@ -8382,7 +8469,7 @@ function CreateAncestryPanel({
8382
8469
  setIsSaving(true);
8383
8470
  const processedSections = processDescriptionForSave(currentInputDesc, currentInputSections);
8384
8471
  setExistingSections(processedSections);
8385
- const updatedRootTree = JSON.parse(JSON.stringify(ancestryMode.tree));
8472
+ const updatedRootTree = applyDescriptionToTree(ancestryMode.tree, currentInputDesc, processedSections);
8386
8473
  const extrasObj = {
8387
8474
  ...toObjectFromCustomProps(customProps.filter((p) => !p.isEditing)),
8388
8475
  is_private: isPrivate
@@ -10676,9 +10763,8 @@ function InSceneQuestForm({
10676
10763
  create_google_doc_action,
10677
10764
  view_google_folder_id
10678
10765
  }) {
10679
- var _a, _b;
10680
10766
  const [name, setName] = useState18("");
10681
- const [assigneeId, setAssigneeId] = useState18("");
10767
+ const [assigneeIds, setAssigneeIds] = useState18([]);
10682
10768
  const [milestoneIds, setMilestoneIds] = useState18([]);
10683
10769
  const [types, setTypes] = useState18(["quest"]);
10684
10770
  const [typeInput, setTypeInput] = useState18("");
@@ -10757,8 +10843,8 @@ function InSceneQuestForm({
10757
10843
  const filteredDependencies = React18.useMemo(() => {
10758
10844
  const search = dependencyInput.toLowerCase().trim();
10759
10845
  return dependencyQuests.filter((q) => {
10760
- var _a2;
10761
- const nameMatch = ((_a2 = q.name) == null ? void 0 : _a2.toLowerCase().includes(search)) || q.raw_title && q.raw_title.toLowerCase().includes(search);
10846
+ var _a;
10847
+ const nameMatch = ((_a = q.name) == null ? void 0 : _a.toLowerCase().includes(search)) || q.raw_title && q.raw_title.toLowerCase().includes(search);
10762
10848
  const notAlreadyAdded = !dependencyIds.includes(q.id);
10763
10849
  return nameMatch && notAlreadyAdded;
10764
10850
  });
@@ -10850,8 +10936,8 @@ function InSceneQuestForm({
10850
10936
  const newProp = createNewCustomProperty(customProps);
10851
10937
  setCustomProps([...customProps, newProp]);
10852
10938
  setTimeout(() => {
10853
- var _a2;
10854
- (_a2 = propsEndRef.current) == null ? void 0 : _a2.scrollIntoView({
10939
+ var _a;
10940
+ (_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({
10855
10941
  behavior: "smooth",
10856
10942
  block: "center"
10857
10943
  });
@@ -10901,7 +10987,10 @@ function InSceneQuestForm({
10901
10987
  type: types,
10902
10988
  color: QUEST_STATUS_COLORS2[status],
10903
10989
  status,
10904
- assignee_id: assigneeId || null,
10990
+ assignee_id: assigneeIds[0] || null,
10991
+ // Legado: primeiro do array
10992
+ assignees: assigneeIds.map((id) => ({ id, status: "pending" })),
10993
+ // NOVO: Estrutura múltipla
10905
10994
  size,
10906
10995
  intensity,
10907
10996
  description: description.trim(),
@@ -10986,13 +11075,25 @@ function InSceneQuestForm({
10986
11075
  {
10987
11076
  type: "button",
10988
11077
  onClick: () => setIsAssigneeDropdownOpen(!isAssigneeDropdownOpen),
10989
- className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 hover:border-white/20 focus:outline-none focus:ring-2 focus:ring-indigo-400/60 transition-colors flex items-center justify-between"
11078
+ className: "w-full bg-slate-800/70 p-2 text-sm rounded-lg border border-white/10 hover:border-white/20 focus:outline-none focus:ring-2 focus:ring-indigo-400/60 transition-colors flex items-center justify-between"
10990
11079
  },
10991
- /* @__PURE__ */ React18.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React18.createElement(FiUser2, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ React18.createElement("span", { className: "text-slate-200 font-medium" }, ((_a = viewMembers.find((m) => m.id === assigneeId)) == null ? void 0 : _a.name) || ((_b = viewMembers.find((m) => m.id === assigneeId)) == null ? void 0 : _b.email) || "Nenhum")),
11080
+ /* @__PURE__ */ React18.createElement("div", { className: "flex flex-wrap items-center gap-1.5 min-h-[24px]" }, /* @__PURE__ */ React18.createElement(FiUser2, { className: "text-slate-400 flex-shrink-0", size: 14 }), assigneeIds.length === 0 ? /* @__PURE__ */ React18.createElement("span", { className: "text-slate-500" }, "Nenhum selecionado") : assigneeIds.map((id) => {
11081
+ const member = viewMembers.find((m) => m.id === id);
11082
+ return /* @__PURE__ */ React18.createElement("span", { key: id, className: "bg-indigo-500/20 text-indigo-300 px-2 py-0.5 rounded text-[10px] font-bold border border-indigo-500/30 flex items-center gap-1" }, (member == null ? void 0 : member.name) || (member == null ? void 0 : member.email) || "Usu\xE1rio", /* @__PURE__ */ React18.createElement(
11083
+ FiX5,
11084
+ {
11085
+ className: "hover:text-white cursor-pointer",
11086
+ onClick: (e) => {
11087
+ e.stopPropagation();
11088
+ setAssigneeIds((prev) => prev.filter((aid) => aid !== id));
11089
+ }
11090
+ }
11091
+ ));
11092
+ })),
10992
11093
  /* @__PURE__ */ React18.createElement(
10993
11094
  FiChevronDown6,
10994
11095
  {
10995
- className: `text-slate-400 transition-transform duration-200 ${isAssigneeDropdownOpen ? "rotate-180" : ""}`
11096
+ className: `text-slate-400 flex-shrink-0 transition-transform duration-200 ${isAssigneeDropdownOpen ? "rotate-180" : ""}`
10996
11097
  }
10997
11098
  )
10998
11099
  ), isAssigneeDropdownOpen && /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(
@@ -11019,13 +11120,13 @@ function InSceneQuestForm({
11019
11120
  "li",
11020
11121
  {
11021
11122
  onClick: () => {
11022
- setAssigneeId("");
11123
+ setAssigneeIds([]);
11023
11124
  setIsAssigneeDropdownOpen(false);
11024
11125
  setAssigneeSearchQuery("");
11025
11126
  },
11026
- className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${!assigneeId ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
11127
+ className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${assigneeIds.length === 0 ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
11027
11128
  },
11028
- "Nenhum"
11129
+ "Limpar sele\xE7\xE3o"
11029
11130
  ), viewMembers.filter((member) => {
11030
11131
  const search = assigneeSearchQuery.toLowerCase();
11031
11132
  return (member.name || "").toLowerCase().includes(search) || (member.email || "").toLowerCase().includes(search);
@@ -11034,13 +11135,16 @@ function InSceneQuestForm({
11034
11135
  {
11035
11136
  key: member.id,
11036
11137
  onClick: () => {
11037
- setAssigneeId(member.id);
11138
+ setAssigneeIds(
11139
+ (prev) => prev.includes(member.id) ? prev.filter((id) => id !== member.id) : [...prev, member.id]
11140
+ );
11038
11141
  setIsAssigneeDropdownOpen(false);
11039
11142
  setAssigneeSearchQuery("");
11040
11143
  },
11041
- className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${assigneeId === member.id ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
11144
+ className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center justify-between gap-2 ${assigneeIds.includes(member.id) ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
11042
11145
  },
11043
- member.name || member.email || member.id
11146
+ /* @__PURE__ */ React18.createElement("div", { className: "flex items-center gap-2" }, member.name || member.email || member.id),
11147
+ assigneeIds.includes(member.id) && /* @__PURE__ */ React18.createElement(FiCheck9, { className: "text-indigo-400" })
11044
11148
  )), viewMembers.filter((member) => {
11045
11149
  const search = assigneeSearchQuery.toLowerCase();
11046
11150
  return (member.name || "").toLowerCase().includes(search) || (member.email || "").toLowerCase().includes(search);
@@ -12216,12 +12320,6 @@ function QuestTimeline({
12216
12320
 
12217
12321
  // src/components/QuestDetailsPanel.jsx
12218
12322
  import { AiOutlineLoading3Quarters as AiOutlineLoading3Quarters4 } from "react-icons/ai";
12219
- var QUEST_STATUS_COLORS3 = {
12220
- "Backlog": "#64748b",
12221
- "In Progress": "#eab308",
12222
- "Review": "#a855f7",
12223
- "Done": "#22c55e"
12224
- };
12225
12323
  function QuestDetailsPanel({
12226
12324
  node,
12227
12325
  onClose,
@@ -12263,6 +12361,7 @@ function QuestDetailsPanel({
12263
12361
  const [status, setStatus] = useState20((node == null ? void 0 : node.status) ?? "Backlog");
12264
12362
  const [size, setSize] = useState20((node == null ? void 0 : node.size) ?? "medium");
12265
12363
  const [assigneeId, setAssigneeId] = useState20((node == null ? void 0 : node.assignee_id) || "");
12364
+ const [assignees, setAssignees] = useState20((node == null ? void 0 : node.assignees) || []);
12266
12365
  const [description, setDescription] = useState20((node == null ? void 0 : node.description) ?? "");
12267
12366
  const [intensity, setIntensity] = useState20((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
12268
12367
  const [milestoneIds, setMilestoneIds] = useState20((node == null ? void 0 : node.milestone_ids) || []);
@@ -12415,6 +12514,7 @@ function QuestDetailsPanel({
12415
12514
  setStatus((node == null ? void 0 : node.status) ?? "Backlog");
12416
12515
  setSize((node == null ? void 0 : node.size) ?? "medium");
12417
12516
  setAssigneeId((node == null ? void 0 : node.assignee_id) || "");
12517
+ setAssignees((node == null ? void 0 : node.assignees) || []);
12418
12518
  setReturnAssigneeId("");
12419
12519
  setDescription((node == null ? void 0 : node.description) ?? "");
12420
12520
  setIntensity((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
@@ -12615,19 +12715,22 @@ ${noteText}` : noteText : entry.notes,
12615
12715
  const updateImageInNote = (id, val) => {
12616
12716
  setNoteImages(noteImages.map((img) => img.id === id ? { ...img, value: val } : img));
12617
12717
  };
12618
- const handleStatusChange = (newStatus) => {
12718
+ const handleStatusChange = (newStatus, overrides = {}) => {
12619
12719
  setStatus(newStatus);
12620
- const newColor = QUEST_STATUS_COLORS3[newStatus];
12720
+ const newColor = QUEST_STATUS_COLORS[newStatus];
12621
12721
  const actorId = (currentUser == null ? void 0 : currentUser.id) || "unknown";
12622
- const currentAssignee = viewMembers.find((m) => String(m.id) === String(assigneeId));
12623
- const assigneeName = (currentAssignee == null ? void 0 : currentAssignee.name) || (currentAssignee == null ? void 0 : currentAssignee.email) || "Nenhum";
12722
+ const currentAssigneeIds = overrides.assignees || assignees;
12723
+ const assigneeNames = currentAssigneeIds.map((a) => {
12724
+ var _a2;
12725
+ return ((_a2 = viewMembers.find((m) => m.id === a.id)) == null ? void 0 : _a2.name) || "Membro";
12726
+ }).join(", ");
12624
12727
  const newEvent = createTimelineEntry(
12625
12728
  actorId,
12626
- `Status "${newStatus}" - Respons\xE1vel: ${assigneeName}`,
12729
+ `Status "${newStatus}" - Respons\xE1veis: ${assigneeNames || "Nenhum"}`,
12627
12730
  "status_changed",
12628
- { metadata: { to_assignee_id: assigneeId } }
12731
+ { metadata: { to_status: newStatus } }
12629
12732
  );
12630
- const newTimeline = [...timeline, newEvent];
12733
+ const newTimeline = [...overrides.timeline || timeline, newEvent];
12631
12734
  setTimeline(newTimeline);
12632
12735
  onColorChange == null ? void 0 : onColorChange(node.id, newColor);
12633
12736
  onDataUpdate == null ? void 0 : onDataUpdate({
@@ -12635,10 +12738,12 @@ ${noteText}` : noteText : entry.notes,
12635
12738
  status: newStatus,
12636
12739
  color: newColor,
12637
12740
  timeline: newTimeline,
12741
+ assignees: currentAssigneeIds,
12638
12742
  Date: questDate,
12639
12743
  recurrence_config: recurrenceConfig
12640
12744
  });
12641
12745
  setHasUnsavedChanges(true);
12746
+ triggerAutoSave({ status: newStatus, timeline: newTimeline, assignees: currentAssigneeIds });
12642
12747
  };
12643
12748
  const handleAddType = (newType) => {
12644
12749
  const trimmed = newType.trim();
@@ -12755,6 +12860,7 @@ ${noteText}` : noteText : entry.notes,
12755
12860
  const currentStandardName = questPrefix ? `${questPrefix} - \xBB ${currentRawTitle || "Sem t\xEDtulo"}` : currentRawTitle;
12756
12861
  const currentTypes = overrides.types !== void 0 ? overrides.types : types;
12757
12862
  const currentAssigneeId = overrides.assigneeId !== void 0 ? overrides.assigneeId : assigneeId;
12863
+ const currentAssignees = overrides.assignees !== void 0 ? overrides.assignees : assignees;
12758
12864
  const currentDescription = overrides.description !== void 0 ? overrides.description : description;
12759
12865
  const currentCustomProps = overrides.customProps !== void 0 ? overrides.customProps : customProps;
12760
12866
  const currentReviewStack = overrides.reviewStack !== void 0 ? overrides.reviewStack : reviewStack;
@@ -12781,9 +12887,10 @@ ${noteText}` : noteText : entry.notes,
12781
12887
  raw_title: currentRawTitle.trim(),
12782
12888
  // Salva o título simples
12783
12889
  type: currentTypes,
12784
- color: QUEST_STATUS_COLORS3[currentStatus],
12890
+ color: QUEST_STATUS_COLORS[currentStatus],
12785
12891
  status: currentStatus,
12786
12892
  assignee_id: currentAssigneeId || null,
12893
+ assignees: currentAssignees,
12787
12894
  size,
12788
12895
  description: currentDescription.trim(),
12789
12896
  description_sections: processedSections,
@@ -12813,6 +12920,19 @@ ${noteText}` : noteText : entry.notes,
12813
12920
  const triggerAutoSave = (overrides = {}) => {
12814
12921
  handleSave(true, overrides);
12815
12922
  };
12923
+ const handleToggleAssignee = (memberId) => {
12924
+ var _a2;
12925
+ const isAlreadyAssignee = assignees.some((a) => a.id === memberId);
12926
+ let updatedAssignees;
12927
+ if (isAlreadyAssignee) {
12928
+ updatedAssignees = assignees.filter((a) => a.id !== memberId);
12929
+ } else {
12930
+ updatedAssignees = [...assignees, { id: memberId, status: "pending" }];
12931
+ }
12932
+ setAssignees(updatedAssignees);
12933
+ setAssigneeId(((_a2 = updatedAssignees[0]) == null ? void 0 : _a2.id) || "");
12934
+ setHasUnsavedChanges(true);
12935
+ };
12816
12936
  const handleCancel = () => {
12817
12937
  if (node) {
12818
12938
  onNameChange == null ? void 0 : onNameChange(node.id, node.name);
@@ -12870,16 +12990,41 @@ ${noteText}` : noteText : entry.notes,
12870
12990
  onImageClick: handleImageClickFromText,
12871
12991
  onSaveDescription: handleSaveDescriptionInline
12872
12992
  }
12873
- ) : /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS3[status]}, transparent)` } }), /* @__PURE__ */ React21.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React21.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ React21.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React21.createElement(FiTarget3, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ React21.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Quest"), /* @__PURE__ */ React21.createElement("button", { onClick: handleCopyLink, className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-sky-400"}`, title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Quest" }, isLinkCopied ? /* @__PURE__ */ React21.createElement(FiCheck11, { size: 12 }) : /* @__PURE__ */ React21.createElement(FiLink7, { size: 12 }))), /* @__PURE__ */ React21.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, standardizedName || (node == null ? void 0 : node.name))), /* @__PURE__ */ React21.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "w-9 h-9 flex-shrink-0 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Cancelar" }, "\xD7")), /* @__PURE__ */ React21.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React21.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React21.createElement("label", { className: "text-xs text-slate-300" }, "Assignee (Respons\xE1vel)"), canEdit ? /* @__PURE__ */ React21.createElement("div", { className: "relative" }, /* @__PURE__ */ React21.createElement(
12993
+ ) : /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS[status]}, transparent)` } }), /* @__PURE__ */ React21.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React21.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ React21.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React21.createElement(FiTarget3, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ React21.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Quest"), /* @__PURE__ */ React21.createElement("button", { onClick: handleCopyLink, className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-sky-400"}`, title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Quest" }, isLinkCopied ? /* @__PURE__ */ React21.createElement(FiCheck11, { size: 12 }) : /* @__PURE__ */ React21.createElement(FiLink7, { size: 12 }))), /* @__PURE__ */ React21.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, standardizedName || (node == null ? void 0 : node.name))), /* @__PURE__ */ React21.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "w-9 h-9 flex-shrink-0 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Cancelar" }, "\xD7")), /* @__PURE__ */ React21.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React21.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React21.createElement("label", { className: "text-xs text-slate-300" }, "Assignee (Respons\xE1vel)"), canEdit ? /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement("div", { className: "flex flex-col gap-2" }, /* @__PURE__ */ React21.createElement("div", { className: "flex flex-wrap gap-2" }, assignees.map((a) => {
12994
+ const member = viewMembers.find((m) => m.id === a.id);
12995
+ const isMe = String(a.id) === String(currentUser == null ? void 0 : currentUser.id);
12996
+ return /* @__PURE__ */ React21.createElement(
12997
+ "div",
12998
+ {
12999
+ key: a.id,
13000
+ className: `flex items-center gap-2 px-3 py-1.5 rounded-lg border transition-all ${a.status === "done" ? "bg-green-500/10 border-green-500/30 text-green-400" : "bg-slate-800/80 border-white/10 text-slate-200"}`
13001
+ },
13002
+ /* @__PURE__ */ React21.createElement(FiUser3, { size: 12, className: a.status === "done" ? "text-green-400" : "text-slate-400" }),
13003
+ /* @__PURE__ */ React21.createElement("span", { className: "text-xs font-medium" }, (member == null ? void 0 : member.name) || (member == null ? void 0 : member.email) || "Membro", isMe && " (Voc\xEA)"),
13004
+ a.status === "done" && /* @__PURE__ */ React21.createElement(FiCheck11, { size: 12 }),
13005
+ canEdit && /* @__PURE__ */ React21.createElement(
13006
+ "button",
13007
+ {
13008
+ onClick: (e) => {
13009
+ e.stopPropagation();
13010
+ handleToggleAssignee(a.id);
13011
+ },
13012
+ className: "ml-1 p-0.5 hover:bg-white/10 rounded transition-colors text-slate-400 hover:text-red-400",
13013
+ title: "Remover respons\xE1vel"
13014
+ },
13015
+ /* @__PURE__ */ React21.createElement(FiX7, { size: 12 })
13016
+ )
13017
+ );
13018
+ }), canEdit && /* @__PURE__ */ React21.createElement(
12874
13019
  "button",
12875
13020
  {
12876
13021
  type: "button",
12877
13022
  onClick: () => setIsAssigneeDropdownOpen(!isAssigneeDropdownOpen),
12878
- className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 hover:border-white/20 focus:outline-none focus:ring-2 focus:ring-indigo-400/60 transition-colors flex items-center justify-between"
13023
+ className: "flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-dashed border-white/20 text-slate-400 hover:border-indigo-400/50 hover:text-indigo-300 transition-all text-xs"
12879
13024
  },
12880
- /* @__PURE__ */ React21.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React21.createElement(FiUser3, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ React21.createElement("span", { className: "text-slate-200 font-medium" }, isAssigneeUndefined ? "Undefined" : (assigneeMember == null ? void 0 : assigneeMember.name) || (assigneeMember == null ? void 0 : assigneeMember.email) || "Nenhum")),
12881
- /* @__PURE__ */ React21.createElement(FiChevronDown7, { className: `text-slate-400 transition-transform duration-200 ${isAssigneeDropdownOpen ? "rotate-180" : ""}` })
12882
- ), isAssigneeDropdownOpen && /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement("div", { className: "fixed inset-0 z-40", onClick: () => {
13025
+ /* @__PURE__ */ React21.createElement(FiPlus9, { size: 12 }),
13026
+ "Adicionar Respons\xE1vel"
13027
+ ))), isAssigneeDropdownOpen && /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement("div", { className: "fixed inset-0 z-40", onClick: () => {
12883
13028
  setIsAssigneeDropdownOpen(false);
12884
13029
  setAssigneeSearchQuery("");
12885
13030
  } }), /* @__PURE__ */ React21.createElement("div", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-900 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden flex flex-col" }, /* @__PURE__ */ React21.createElement("div", { className: "p-2 border-b border-white/5 bg-white/5 flex items-center gap-2" }, /* @__PURE__ */ React21.createElement(FiSearch7, { className: "text-slate-500", size: 14 }), /* @__PURE__ */ React21.createElement(
@@ -12893,25 +13038,23 @@ ${noteText}` : noteText : entry.notes,
12893
13038
  className: "bg-transparent border-none outline-none text-xs text-white placeholder-slate-500 w-full",
12894
13039
  onClick: (e) => e.stopPropagation()
12895
13040
  }
12896
- )), /* @__PURE__ */ React21.createElement("ul", { className: "max-h-48 overflow-y-auto custom-scrollbar" }, /* @__PURE__ */ React21.createElement(
13041
+ )), /* @__PURE__ */ React21.createElement("ul", { className: "max-h-48 overflow-y-auto custom-scrollbar" }, viewMembers.filter((member) => {
13042
+ const search = assigneeSearchQuery.toLowerCase();
13043
+ const isNotAlreadyAssignee = !assignees.some((a) => a.id === member.id);
13044
+ return isNotAlreadyAssignee && ((member.name || "").toLowerCase().includes(search) || (member.email || "").toLowerCase().includes(search));
13045
+ }).map((member) => /* @__PURE__ */ React21.createElement(
12897
13046
  "li",
12898
13047
  {
13048
+ key: member.id,
12899
13049
  onClick: () => {
12900
- setAssigneeId("");
12901
- const newTimeline = [...timeline, createTimelineEntry(
12902
- (currentUser == null ? void 0 : currentUser.id) || "unknown",
12903
- `Status "${status}" - Respons\xE1vel: Nenhum`,
12904
- "status_changed"
12905
- )];
12906
- setTimeline(newTimeline);
12907
- setHasUnsavedChanges(true);
13050
+ handleToggleAssignee(member.id);
12908
13051
  setIsAssigneeDropdownOpen(false);
12909
13052
  setAssigneeSearchQuery("");
12910
13053
  },
12911
- className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${!assigneeId ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
13054
+ className: "px-3 py-2.5 text-sm cursor-pointer text-slate-300 hover:bg-white/5 hover:text-white transition-colors flex items-center gap-2"
12912
13055
  },
12913
- "Nenhum"
12914
- ), isAssigneeUndefined && /* @__PURE__ */ React21.createElement(
13056
+ member.name || member.email || member.id
13057
+ )), isAssigneeUndefined && /* @__PURE__ */ React21.createElement(
12915
13058
  "li",
12916
13059
  {
12917
13060
  onClick: () => {
@@ -12923,27 +13066,12 @@ ${noteText}` : noteText : entry.notes,
12923
13066
  "Undefined (Removido)"
12924
13067
  ), viewMembers.filter((member) => {
12925
13068
  const search = assigneeSearchQuery.toLowerCase();
12926
- return (member.name || "").toLowerCase().includes(search) || (member.email || "").toLowerCase().includes(search);
12927
- }).map((member) => /* @__PURE__ */ React21.createElement(
12928
- "li",
12929
- {
12930
- key: member.id,
12931
- onClick: () => {
12932
- setAssigneeId(member.id);
12933
- const newTimeline = [...timeline, createTimelineEntry(
12934
- (currentUser == null ? void 0 : currentUser.id) || "unknown",
12935
- `Status "${status}" - Respons\xE1vel: ${member.name || member.email}`,
12936
- "status_changed"
12937
- )];
12938
- setTimeline(newTimeline);
12939
- setHasUnsavedChanges(true);
12940
- setIsAssigneeDropdownOpen(false);
12941
- setAssigneeSearchQuery("");
12942
- },
12943
- className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${assigneeId === member.id ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
12944
- },
12945
- member.name || member.email || member.id
12946
- )))))) : /* @__PURE__ */ React21.createElement("div", { className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 text-slate-400 flex items-center gap-2" }, /* @__PURE__ */ React21.createElement(FiUser3, { className: "opacity-50", size: 14 }), assigneeId ? assigneeMember ? assigneeMember.name || assigneeMember.email : "Undefined" : "Nenhum")), /* @__PURE__ */ React21.createElement("div", { className: "space-y-3 pt-4 border-t border-white/5" }, /* @__PURE__ */ React21.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React21.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React21.createElement(FiGitBranch4, { className: "text-indigo-400", size: 14 }), /* @__PURE__ */ React21.createElement("h3", { className: "text-[11px] uppercase font-bold text-slate-500 tracking-wider" }, "Estruturas Visuais"))), /* @__PURE__ */ React21.createElement("div", { className: "bg-slate-900/60 p-2 rounded-xl border border-white/10 flex flex-col gap-2" }, /* @__PURE__ */ React21.createElement(
13069
+ const isNotAlreadyAssignee = !assignees.some((a) => a.id === member.id);
13070
+ return isNotAlreadyAssignee && ((member.name || "").toLowerCase().includes(search) || (member.email || "").toLowerCase().includes(search));
13071
+ }).length === 0 && /* @__PURE__ */ React21.createElement("li", { className: "px-3 py-4 text-xs text-slate-500 text-center italic" }, "Nenhum membro dispon\xEDvel"))))) : /* @__PURE__ */ React21.createElement("div", { className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 text-slate-400 flex flex-wrap gap-2" }, /* @__PURE__ */ React21.createElement(FiUser3, { className: "opacity-50", size: 14 }), assignees.length > 0 ? assignees.map((a) => {
13072
+ const member = viewMembers.find((m) => m.id === a.id);
13073
+ return /* @__PURE__ */ React21.createElement("span", { key: a.id, className: a.status === "done" ? "text-green-400" : "" }, (member == null ? void 0 : member.name) || (member == null ? void 0 : member.email) || "Membro", a.status === "done" && " (\u2713)");
13074
+ }) : "Nenhum")), /* @__PURE__ */ React21.createElement("div", { className: "space-y-3 pt-4 border-t border-white/5" }, /* @__PURE__ */ React21.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React21.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React21.createElement(FiGitBranch4, { className: "text-indigo-400", size: 14 }), /* @__PURE__ */ React21.createElement("h3", { className: "text-[11px] uppercase font-bold text-slate-500 tracking-wider" }, "Estruturas Visuais"))), /* @__PURE__ */ React21.createElement("div", { className: "bg-slate-900/60 p-2 rounded-xl border border-white/10 flex flex-col gap-2" }, /* @__PURE__ */ React21.createElement(
12947
13075
  "button",
12948
13076
  {
12949
13077
  type: "button",
@@ -13212,9 +13340,9 @@ ${noteText}` : noteText : entry.notes,
13212
13340
  disabled: !canEdit,
13213
13341
  className: `w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 transition-colors flex items-center justify-between ${canEdit ? "hover:border-white/20 focus:ring-2 focus:ring-indigo-400/60 cursor-pointer" : "cursor-default opacity-80"}`
13214
13342
  },
13215
- /* @__PURE__ */ React21.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React21.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor: QUEST_STATUS_COLORS3[status] } }), /* @__PURE__ */ React21.createElement("span", { className: "text-slate-200 font-medium" }, status)),
13343
+ /* @__PURE__ */ React21.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React21.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor: QUEST_STATUS_COLORS[status] } }), /* @__PURE__ */ React21.createElement("span", { className: "text-slate-200 font-medium" }, status)),
13216
13344
  canEdit && /* @__PURE__ */ React21.createElement(FiChevronDown7, { className: `text-slate-400 transition-transform duration-200 ${isStatusDropdownOpen ? "rotate-180" : ""}` })
13217
- ), isStatusDropdownOpen && canEdit && /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ React21.createElement("ul", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-800 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden" }, Object.keys(QUEST_STATUS_COLORS3).map((s) => {
13345
+ ), isStatusDropdownOpen && canEdit && /* @__PURE__ */ React21.createElement(React21.Fragment, null, /* @__PURE__ */ React21.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ React21.createElement("ul", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-800 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden" }, Object.keys(QUEST_STATUS_COLORS).map((s) => {
13218
13346
  const isBacklog = s === "Backlog";
13219
13347
  const isDisabled = !isBacklog && blockedStatus.isBlocked;
13220
13348
  return /* @__PURE__ */ React21.createElement(
@@ -13230,7 +13358,7 @@ ${noteText}` : noteText : entry.notes,
13230
13358
  className: `px-3 py-2.5 text-sm transition-colors flex items-center justify-between ${status === s ? "bg-indigo-500/20 text-white" : "text-slate-300"} ${isDisabled ? "opacity-40 cursor-not-allowed grayscale" : "cursor-pointer hover:bg-white/5 hover:text-white"}`,
13231
13359
  title: isDisabled ? `Bloqueado por depend\xEAncias: ${blockedStatus.pendingDependencies.map((d) => d.raw_title || d.name).join(", ")}` : ""
13232
13360
  },
13233
- /* @__PURE__ */ React21.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React21.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS3[s] } }), s),
13361
+ /* @__PURE__ */ React21.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React21.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS[s] } }), s),
13234
13362
  isDisabled && /* @__PURE__ */ React21.createElement(FiRepeat2, { className: "text-amber-400/60 rotate-180", size: 12 })
13235
13363
  );
13236
13364
  }))))), /* @__PURE__ */ React21.createElement("div", { className: "pt-4 border-t border-white/5 mt-2" }, /* @__PURE__ */ React21.createElement("div", { className: "flex items-center justify-between mb-3" }, /* @__PURE__ */ React21.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React21.createElement(FiRepeat2, { className: `w-3.5 h-3.5 ${recurrenceConfig.enabled ? "text-indigo-400" : "text-slate-500"}` }), /* @__PURE__ */ React21.createElement("span", { className: "text-xs text-slate-300 font-medium uppercase tracking-wider" }, "Recorr\xEAncia")), /* @__PURE__ */ React21.createElement(
@@ -14496,7 +14624,7 @@ import React29, { useEffect as useEffect23, useRef as useRef20, useState as useS
14496
14624
 
14497
14625
  // src/components/MentionPopover.jsx
14498
14626
  import React28, { useEffect as useEffect22, useRef as useRef19, useState as useState26, useMemo as useMemo12 } from "react";
14499
- import { FiLayers as FiLayers7, FiCheckSquare as FiCheckSquare3, FiGitBranch as FiGitBranch5, FiBox } from "react-icons/fi";
14627
+ import { FiLayers as FiLayers7, FiCheckSquare as FiCheckSquare3, FiGitBranch as FiGitBranch5, FiBox, FiCornerUpRight as FiCornerUpRight4 } from "react-icons/fi";
14500
14628
  var TYPE_CONFIG = {
14501
14629
  ancestry: { Icon: FiLayers7, color: "text-indigo-400", label: "Ancestralidade" },
14502
14630
  quest: { Icon: FiCheckSquare3, color: "text-emerald-400", label: "Quest" },
@@ -14547,13 +14675,14 @@ function MentionPopover({ query, items, position, onSelect, onClose }) {
14547
14675
  "div",
14548
14676
  {
14549
14677
  style: { top: position.top, left: position.left, position: "fixed", zIndex: 9999 },
14550
- className: "bg-slate-900 border border-white/10 rounded-xl shadow-2xl py-1.5 min-w-[260px] max-h-[240px] overflow-y-auto custom-scrollbar animate-in fade-in zoom-in-95 duration-100",
14678
+ className: "bg-slate-900 border border-white/10 rounded-xl shadow-2xl py-1.5 min-w-[300px] max-h-[320px] overflow-y-auto custom-scrollbar animate-in fade-in zoom-in-95 duration-100",
14551
14679
  ref: listRef,
14552
14680
  onMouseDown: (e) => e.preventDefault()
14553
14681
  },
14554
14682
  filtered.length === 0 ? /* @__PURE__ */ React28.createElement("div", { className: "px-4 py-3 text-xs text-slate-500" }, "Nenhum resultado para", " ", /* @__PURE__ */ React28.createElement("span", { className: "text-slate-300 font-medium" }, '"', query, '"')) : filtered.map((item, idx) => {
14555
14683
  const config = TYPE_CONFIG[item.type] || TYPE_CONFIG.node;
14556
14684
  const { Icon } = config;
14685
+ const isActive = idx === activeIndex;
14557
14686
  return /* @__PURE__ */ React28.createElement(
14558
14687
  "div",
14559
14688
  {
@@ -14563,11 +14692,11 @@ function MentionPopover({ query, items, position, onSelect, onClose }) {
14563
14692
  onSelect(item);
14564
14693
  },
14565
14694
  onMouseEnter: () => setActiveIndex(idx),
14566
- className: `flex items-center gap-2.5 px-3 py-2 cursor-pointer text-sm transition-colors duration-100 ${idx === activeIndex ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5"}`
14695
+ className: `flex items-center gap-3 px-3 py-2 cursor-pointer text-sm transition-colors duration-100 ${isActive ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5"}`
14567
14696
  },
14568
- /* @__PURE__ */ React28.createElement(Icon, { size: 13, className: config.color }),
14569
- /* @__PURE__ */ React28.createElement("span", { className: "flex-1 truncate font-medium" }, item.searchLabel || "Sem Nome"),
14570
- /* @__PURE__ */ React28.createElement("span", { className: "text-[9px] px-1.5 py-0.5 rounded-full bg-white/5 text-slate-500 border border-white/5 uppercase tracking-wide shrink-0" }, config.label)
14697
+ /* @__PURE__ */ React28.createElement("div", { className: `w-7 h-7 rounded bg-slate-800 flex items-center justify-center shrink-0 border border-white/5 ${isActive ? "border-indigo-500/50" : ""}` }, /* @__PURE__ */ React28.createElement(Icon, { size: 14, className: config.color })),
14698
+ /* @__PURE__ */ React28.createElement("div", { className: "flex-1 min-w-0 flex flex-col py-0.5" }, /* @__PURE__ */ React28.createElement("span", { className: "truncate font-medium leading-tight" }, item.searchLabel || "Sem Nome"), item.type === "ancestry" ? /* @__PURE__ */ React28.createElement("span", { className: `text-[10px] truncate flex items-center gap-1 mt-0.5 ${isActive ? "text-indigo-200" : "text-slate-500"}` }, /* @__PURE__ */ React28.createElement(FiCornerUpRight4, { size: 10, className: "opacity-70" }), /* @__PURE__ */ React28.createElement("span", { className: "opacity-70" }, "Origem:"), " ", item.originNodeName) : item.nodeTypeLabel && /* @__PURE__ */ React28.createElement("span", { className: `text-[10px] uppercase font-bold tracking-tight truncate mt-0.5 ${isActive ? "text-indigo-100" : "text-slate-500"}` }, item.nodeTypeLabel)),
14699
+ /* @__PURE__ */ React28.createElement("span", { className: "text-[9px] px-1.5 py-0.5 rounded-full bg-white/5 text-slate-500 border border-white/5 uppercase tracking-wide shrink-0 self-start mt-1" }, config.label)
14571
14700
  );
14572
14701
  })
14573
14702
  );
@@ -15166,6 +15295,13 @@ function Boards({
15166
15295
  setIsLoaded(true);
15167
15296
  }
15168
15297
  }, [initialBoardItems, isLoaded]);
15298
+ const nodeNamesMap = useMemo13(() => {
15299
+ const map = /* @__PURE__ */ new Map();
15300
+ if (availableNodes) {
15301
+ availableNodes.forEach((n) => map.set(String(n.id), n.name));
15302
+ }
15303
+ return map;
15304
+ }, [availableNodes]);
15169
15305
  const allSearchableItems = useMemo13(() => {
15170
15306
  const items = [];
15171
15307
  availableAncestries.forEach((anc) => {
@@ -15174,24 +15310,26 @@ function Boards({
15174
15310
  id: String(anc.ancestry_id),
15175
15311
  type: "ancestry",
15176
15312
  searchLabel: anc.name || "",
15177
- searchDesc: anc.description || ""
15313
+ searchDesc: anc.description || "",
15314
+ originNodeName: nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido"
15178
15315
  });
15179
15316
  });
15180
15317
  availableNodes.forEach((node) => {
15181
15318
  var _a;
15182
- let type = "node";
15183
- if (node.is_quest) type = "quest";
15184
- else if ((_a = node.version_node) == null ? void 0 : _a.is_version) type = "version";
15319
+ let mentionType = "node";
15320
+ if (node.is_quest) mentionType = "quest";
15321
+ else if ((_a = node.version_node) == null ? void 0 : _a.is_version) mentionType = "version";
15185
15322
  items.push({
15186
15323
  ...node,
15187
15324
  id: String(node.id),
15188
- type,
15325
+ type: mentionType,
15189
15326
  searchLabel: node.name || node.raw_title || "",
15190
- searchDesc: node.description || ""
15327
+ searchDesc: node.description || "",
15328
+ nodeTypeLabel: Array.isArray(node.type) ? node.type.join(" \u2022 ") : node.type
15191
15329
  });
15192
15330
  });
15193
15331
  return items;
15194
- }, [availableAncestries, availableNodes]);
15332
+ }, [availableAncestries, availableNodes, nodeNamesMap]);
15195
15333
  useEffect24(() => {
15196
15334
  if (!isLoaded || !onSave) return;
15197
15335
  const id = setTimeout(async () => {
@@ -15633,7 +15771,6 @@ var TIMELINE_INTERVAL_BAR_OPACITY = 0.85;
15633
15771
  var TIMELINE_GOLD_COLOR = 16766720;
15634
15772
  var QUEST_LENS_COLUMN_SPACING = 80;
15635
15773
  var QUEST_LENS_ROW_SPACING = 40;
15636
- var QUEST_STATUS_ORDER = ["Backlog", "In Progress", "Review", "Done"];
15637
15774
  var getAllNodeIdsFromTree = (treeNode) => {
15638
15775
  const ids = /* @__PURE__ */ new Set();
15639
15776
  function traverse(node) {
@@ -15686,6 +15823,7 @@ function XViewScene({
15686
15823
  check_user_permission,
15687
15824
  get_view_members,
15688
15825
  create_google_doc_action,
15826
+ copy_google_doc_action,
15689
15827
  open_google_picker_action,
15690
15828
  upsert_quest_firestore,
15691
15829
  delete_quest_firestore,
@@ -16864,13 +17002,13 @@ function XViewScene({
16864
17002
  sortedTimePoints.forEach((ms, idx) => {
16865
17003
  timeToYMap.set(ms, idx * TIMELINE_LAYER_SPACING_Y);
16866
17004
  });
16867
- const startX = -((QUEST_STATUS_ORDER.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
17005
+ const startX = -((QUEST_STATUSES.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
16868
17006
  let sumX = 0;
16869
17007
  let sumY = 0;
16870
17008
  let questCount = 0;
16871
17009
  const positionGroups = /* @__PURE__ */ new Map();
16872
17010
  const NODE_X_GAP = 22;
16873
- QUEST_STATUS_ORDER.forEach((statusName) => {
17011
+ QUEST_STATUSES.forEach((statusName) => {
16874
17012
  const questsInCol = questsByStatus[statusName];
16875
17013
  questsInCol.forEach((q, rowIndex) => {
16876
17014
  const timeInfo = questTimeInfos.get(String(q.id)) || {
@@ -16951,7 +17089,7 @@ function XViewScene({
16951
17089
  }
16952
17090
  }
16953
17091
  });
16954
- QUEST_STATUS_ORDER.forEach((statusName, colIndex) => {
17092
+ QUEST_STATUSES.forEach((statusName, colIndex) => {
16955
17093
  if (status2 && status2 !== statusName) return;
16956
17094
  const questsInCol = questsByStatus[statusName];
16957
17095
  const colX = startX + colIndex * QUEST_LENS_COLUMN_SPACING;
@@ -17800,19 +17938,6 @@ function XViewScene({
17800
17938
  const dirX = (keysPressed["ArrowRight"] ? 1 : 0) - (keysPressed["ArrowLeft"] ? 1 : 0);
17801
17939
  const dirY = (keysPressed["ArrowUp"] ? 1 : 0) - (keysPressed["ArrowDown"] ? 1 : 0);
17802
17940
  if (isCtrl && (dirX !== 0 || dirY !== 0)) {
17803
- const offset = sceneCamera.position.clone().sub(sceneControls.target);
17804
- const spherical = new THREE3.Spherical().setFromVector3(offset);
17805
- spherical.theta += dirX * rotateSpeed;
17806
- spherical.phi -= dirY * rotateSpeed;
17807
- spherical.makeSafe();
17808
- offset.setFromSpherical(spherical);
17809
- sceneCamera.position.copy(sceneControls.target).add(offset);
17810
- } else if (isShift && dirY !== 0) {
17811
- const factor = keysPressed["ArrowUp"] ? zoomInFactor : zoomOutFactor;
17812
- const offset = sceneCamera.position.clone().sub(sceneControls.target);
17813
- offset.multiplyScalar(factor);
17814
- sceneCamera.position.copy(sceneControls.target).add(offset);
17815
- } else if (!isCtrl && !isShift && (dirX !== 0 || dirY !== 0)) {
17816
17941
  const distance = sceneCamera.position.distanceTo(
17817
17942
  sceneControls.target
17818
17943
  );
@@ -17829,6 +17954,19 @@ function XViewScene({
17829
17954
  vecY.multiplyScalar(dirY * currentPanSpeed);
17830
17955
  sceneCamera.position.add(vecX).add(vecY);
17831
17956
  sceneControls.target.add(vecX).add(vecY);
17957
+ } else if (isShift && dirY !== 0) {
17958
+ const factor = keysPressed["ArrowUp"] ? zoomInFactor : zoomOutFactor;
17959
+ const offset = sceneCamera.position.clone().sub(sceneControls.target);
17960
+ offset.multiplyScalar(factor);
17961
+ sceneCamera.position.copy(sceneControls.target).add(offset);
17962
+ } else if (!isCtrl && !isShift && (dirX !== 0 || dirY !== 0)) {
17963
+ const offset = sceneCamera.position.clone().sub(sceneControls.target);
17964
+ const spherical = new THREE3.Spherical().setFromVector3(offset);
17965
+ spherical.theta += dirX * rotateSpeed;
17966
+ spherical.phi -= dirY * rotateSpeed;
17967
+ spherical.makeSafe();
17968
+ offset.setFromSpherical(spherical);
17969
+ sceneCamera.position.copy(sceneControls.target).add(offset);
17832
17970
  }
17833
17971
  }
17834
17972
  stateRef.current.controls.update();
@@ -18203,7 +18341,8 @@ function XViewScene({
18203
18341
  upsert_quest_link_firestore,
18204
18342
  delete_quest_link_firestore,
18205
18343
  upsert_milestone_firestore,
18206
- update_view_counter
18344
+ update_view_counter,
18345
+ copy_google_doc_action
18207
18346
  }
18208
18347
  };
18209
18348
  },
@@ -18228,7 +18367,8 @@ function XViewScene({
18228
18367
  upsert_quest_link_firestore,
18229
18368
  delete_quest_link_firestore,
18230
18369
  upsert_milestone_firestore,
18231
- update_view_counter
18370
+ update_view_counter,
18371
+ copy_google_doc_action
18232
18372
  ]
18233
18373
  );
18234
18374
  const handleStartVersioning = (nodeData) => {
@@ -18236,7 +18376,7 @@ function XViewScene({
18236
18376
  };
18237
18377
  const handleStartQuestQuick = useCallback7(
18238
18378
  (questNode) => {
18239
- var _a2, _b2, _c2;
18379
+ var _a2, _b2, _c2, _d2, _e2, _f2;
18240
18380
  if (!questNode || !actionHandlerContext) return;
18241
18381
  const allParentNodes = Object.values(parentDataRef.current).flatMap(
18242
18382
  (fileData) => fileData.nodes || []
@@ -18257,19 +18397,29 @@ function XViewScene({
18257
18397
  timelineEndLabel,
18258
18398
  ...cleanQuestNode
18259
18399
  } = questNode;
18400
+ let updatedAssignees = [...cleanQuestNode.assignees || []];
18401
+ const isJoining = cleanQuestNode.status === "In Progress";
18402
+ const alreadyIn = updatedAssignees.some((a) => {
18403
+ var _a3;
18404
+ return String(a.id) === String((_a3 = session == null ? void 0 : session.user) == null ? void 0 : _a3.id);
18405
+ });
18406
+ if (!alreadyIn) {
18407
+ updatedAssignees.push({ id: (_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id, status: "pending" });
18408
+ }
18260
18409
  const newTimeline = [
18261
18410
  ...cleanQuestNode.timeline || [],
18262
18411
  createTimelineEntry(
18263
- ((_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id) || "unknown",
18264
- `Status "In Progress" - Respons\xE1vel: ${((_b2 = session == null ? void 0 : session.user) == null ? void 0 : _b2.name) || "usu\xE1rio"}`,
18265
- "status_changed"
18412
+ ((_b2 = session == null ? void 0 : session.user) == null ? void 0 : _b2.id) || "unknown",
18413
+ isJoining ? `${((_c2 = session == null ? void 0 : session.user) == null ? void 0 : _c2.name) || "Usu\xE1rio"} entrou na quest.` : `Status "In Progress" - Respons\xE1vel: ${((_d2 = session == null ? void 0 : session.user) == null ? void 0 : _d2.name) || "usu\xE1rio"}`,
18414
+ isJoining ? "assignee_added" : "status_changed"
18266
18415
  )
18267
18416
  ];
18268
18417
  const updatedNode = {
18269
18418
  ...cleanQuestNode,
18270
18419
  status: "In Progress",
18271
18420
  color: "#eab308",
18272
- assignee_id: (_c2 = session == null ? void 0 : session.user) == null ? void 0 : _c2.id,
18421
+ assignee_id: ((_e2 = updatedAssignees[0]) == null ? void 0 : _e2.id) || ((_f2 = session == null ? void 0 : session.user) == null ? void 0 : _f2.id),
18422
+ assignees: updatedAssignees,
18273
18423
  timeline: newTimeline
18274
18424
  };
18275
18425
  if (userActionHandlers.handleSaveNodeDetails) {
@@ -18285,7 +18435,7 @@ function XViewScene({
18285
18435
  );
18286
18436
  const handleFinishQuestQuick = useCallback7(
18287
18437
  (questNode) => {
18288
- var _a2, _b2, _c2, _d2;
18438
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2;
18289
18439
  if (!questNode || !actionHandlerContext) return;
18290
18440
  const {
18291
18441
  labelObject,
@@ -18296,7 +18446,44 @@ function XViewScene({
18296
18446
  timelineEndLabel,
18297
18447
  ...cleanQuestNode
18298
18448
  } = questNode;
18299
- let nextAssigneeId = cleanQuestNode.assignee_id;
18449
+ let updatedAssignees = [...cleanQuestNode.assignees || []];
18450
+ if (updatedAssignees.length === 0 && cleanQuestNode.assignee_id) {
18451
+ updatedAssignees = [{ id: cleanQuestNode.assignee_id, status: cleanQuestNode.status === "Done" ? "done" : "pending" }];
18452
+ }
18453
+ const isAssignee = updatedAssignees.some((a) => {
18454
+ var _a3;
18455
+ return String(a.id) === String((_a3 = session == null ? void 0 : session.user) == null ? void 0 : _a3.id);
18456
+ });
18457
+ if (isAssignee) {
18458
+ updatedAssignees = updatedAssignees.map(
18459
+ (a) => {
18460
+ var _a3;
18461
+ return String(a.id) === String((_a3 = session == null ? void 0 : session.user) == null ? void 0 : _a3.id) ? { ...a, status: "done", completed_at: Date.now() } : a;
18462
+ }
18463
+ );
18464
+ }
18465
+ const allDone = checkAllAssigneesDone(updatedAssignees);
18466
+ if (!allDone) {
18467
+ const newTimeline2 = [
18468
+ ...cleanQuestNode.timeline || [],
18469
+ createTimelineEntry(
18470
+ ((_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id) || "unknown",
18471
+ `${((_b2 = session == null ? void 0 : session.user) == null ? void 0 : _b2.name) || "Usu\xE1rio"} concluiu sua etapa individual.`,
18472
+ "comment"
18473
+ )
18474
+ ];
18475
+ const updatedNode2 = {
18476
+ ...cleanQuestNode,
18477
+ assignees: updatedAssignees,
18478
+ timeline: newTimeline2
18479
+ };
18480
+ if (userActionHandlers.handleSaveNodeDetails) {
18481
+ userActionHandlers.handleSaveNodeDetails(actionHandlerContext, updatedNode2, true);
18482
+ }
18483
+ setDetailsNode(updatedNode2);
18484
+ return;
18485
+ }
18486
+ let nextAssigneeId = ((_c2 = updatedAssignees[0]) == null ? void 0 : _c2.id) || cleanQuestNode.assignee_id;
18300
18487
  let nextStatus = "Done";
18301
18488
  let newTimeline = [...cleanQuestNode.timeline || []];
18302
18489
  const reviewStack = [...cleanQuestNode.reviewStack || []];
@@ -18327,7 +18514,7 @@ function XViewScene({
18327
18514
  nextStatus = "Done";
18328
18515
  }
18329
18516
  if (nextStatus === "Review") {
18330
- const nextReviewerName = ((_a2 = viewMembers.find((m) => m.id === nextAssigneeId)) == null ? void 0 : _a2.name) || "revisor";
18517
+ const nextReviewerName = ((_d2 = viewMembers.find((m) => m.id === nextAssigneeId)) == null ? void 0 : _d2.name) || "revisor";
18331
18518
  newTimeline.push(
18332
18519
  createTimelineEntry(
18333
18520
  "system",
@@ -18337,15 +18524,15 @@ function XViewScene({
18337
18524
  )
18338
18525
  );
18339
18526
  } else if (nextStatus === "Done") {
18340
- const finisherName = ((_b2 = viewMembers.find(
18527
+ const finisherName = ((_e2 = viewMembers.find(
18341
18528
  (m) => {
18342
18529
  var _a3;
18343
18530
  return m.id === (((_a3 = session == null ? void 0 : session.user) == null ? void 0 : _a3.id) || cleanQuestNode.assignee_id);
18344
18531
  }
18345
- )) == null ? void 0 : _b2.name) || ((_c2 = session == null ? void 0 : session.user) == null ? void 0 : _c2.name) || "respons\xE1vel";
18532
+ )) == null ? void 0 : _e2.name) || ((_f2 = session == null ? void 0 : session.user) == null ? void 0 : _f2.name) || "respons\xE1vel";
18346
18533
  newTimeline.push(
18347
18534
  createTimelineEntry(
18348
- ((_d2 = session == null ? void 0 : session.user) == null ? void 0 : _d2.id) || cleanQuestNode.assignee_id,
18535
+ ((_g2 = session == null ? void 0 : session.user) == null ? void 0 : _g2.id) || cleanQuestNode.assignee_id,
18349
18536
  `Status "Done" - Finalizado por ${finisherName}`,
18350
18537
  "status_changed"
18351
18538
  )
@@ -18354,8 +18541,9 @@ function XViewScene({
18354
18541
  const updatedNode = {
18355
18542
  ...cleanQuestNode,
18356
18543
  status: nextStatus,
18357
- color: nextStatus === "Done" ? "#22c55e" : "#a855f7",
18358
- assignee_id: nextAssigneeId,
18544
+ color: QUEST_STATUS_COLORS[nextStatus],
18545
+ assignee_id: nextAssigneeId || null,
18546
+ assignees: updatedAssignees,
18359
18547
  reviewStack,
18360
18548
  timeline: newTimeline
18361
18549
  };
@@ -18594,6 +18782,11 @@ function XViewScene({
18594
18782
  }
18595
18783
  });
18596
18784
  }
18785
+ console.log("[handleRenderAncestry] Start", {
18786
+ ancestryId: ancestryObject.ancestry_id,
18787
+ allowedSectionIds: allowedSectionIds ? Array.from(allowedSectionIds) : null,
18788
+ activeSectionIdForFocus
18789
+ });
18597
18790
  const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
18598
18791
  const currentRenderLimit = stateRef.current.maxAncestryRenderIndex || 0;
18599
18792
  const isFullRenderRequest = !normalizedAllowedIds;
@@ -18891,6 +19084,11 @@ function XViewScene({
18891
19084
  let currentAnchorPosition = currentAnchorMesh.userData.id ? targetPositionsCache.get(String(currentAnchorMesh.userData.id)) || currentAnchorMesh.position : currentAnchorMesh.position;
18892
19085
  for (const section of sections) {
18893
19086
  const deveRenderizar = checkShouldRender(section);
19087
+ console.log("[handleRenderAncestry] Section check:", {
19088
+ id: section.id,
19089
+ numericId: section.section_numeric_id,
19090
+ deveRenderizar
19091
+ });
18894
19092
  if (deveRenderizar) {
18895
19093
  const sectionNodes = section.children || [];
18896
19094
  if (sectionNodes.length > 0) {
@@ -19732,8 +19930,15 @@ function XViewScene({
19732
19930
  }, []);
19733
19931
  const handleSaveAncestry = useCallback7(
19734
19932
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
19933
+ var _a2, _b2;
19735
19934
  const treeToUse = treeOverride || ancestryMode.tree;
19736
19935
  const { isEditMode, currentAncestryId } = ancestryMode;
19936
+ console.log("[handleSaveAncestry] received:", {
19937
+ name: ancestryName,
19938
+ descLength: ancestryDescription == null ? void 0 : ancestryDescription.length,
19939
+ sectionsCount: ancestrySections == null ? void 0 : ancestrySections.length,
19940
+ treeRoot: (_a2 = treeToUse.node) == null ? void 0 : _a2.id
19941
+ });
19737
19942
  if (!treeToUse || !treeToUse.node) {
19738
19943
  alert(
19739
19944
  "Erro: A estrutura da ancestralidade \xE9 inv\xE1lida (Node raiz ausente)."
@@ -19937,6 +20142,12 @@ function XViewScene({
19937
20142
  currentAncestryId: ancestryObjectToSave.ancestry_id
19938
20143
  }));
19939
20144
  }
20145
+ if (readingMode.isActive && ((_b2 = readingMode.ancestry) == null ? void 0 : _b2.ancestry_id) === ancestryObjectToSave.ancestry_id) {
20146
+ setReadingMode((prev) => ({
20147
+ ...prev,
20148
+ ancestry: ancestryObjectToSave
20149
+ }));
20150
+ }
19940
20151
  handleRenderAncestry({
19941
20152
  ...ancestryObjectToSave,
19942
20153
  _forceUpdate: true
@@ -21226,7 +21437,11 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21226
21437
  if (questsResponse.success) {
21227
21438
  return {
21228
21439
  success: true,
21229
- data: questsResponse.data || { nodes: [], links: [], milestones: [] },
21440
+ data: questsResponse.data || {
21441
+ nodes: [],
21442
+ links: [],
21443
+ milestones: []
21444
+ },
21230
21445
  quest_counter: questsResponse.quest_counter
21231
21446
  };
21232
21447
  }