@lv-x-software-house/x_view 1.3.0-dev.2 → 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 +356 -151
  2. package/dist/index.mjs +356 -151
  3. package/package.json +4 -2
package/dist/index.js CHANGED
@@ -2307,7 +2307,7 @@ var userActionHandlers = {
2307
2307
  }
2308
2308
  },
2309
2309
  handleSaveNodeDetails: async (context, updatedNode, keepOpen = false) => {
2310
- var _a, _b, _c, _d;
2310
+ var _a, _b, _c, _d, _e, _f;
2311
2311
  const { graphDataRef, sceneDataRef, stateRef, setters } = context;
2312
2312
  if (!graphDataRef.current || !sceneDataRef.current) return;
2313
2313
  const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
@@ -2356,35 +2356,41 @@ var userActionHandlers = {
2356
2356
  const isNewDone = oldNode.status !== "Done" && nodeToSave.status === "Done";
2357
2357
  specificParentData.nodes[nodeIndex] = { ...nodeToSave };
2358
2358
  if (isNewDone && nodeToSave.is_quest && ((_b = nodeToSave.recurrence_config) == null ? void 0 : _b.enabled)) {
2359
+ const rootId = ((_c = nodeToSave.version_node) == null ? void 0 : _c.parent_node) || nodeToSave.id;
2360
+ const rootNode = specificParentData.nodes.find((n) => String(n.id) === String(rootId)) || nodeToSave;
2359
2361
  const nextDateObj = calculateNextRecurrenceDate(
2360
- nodeToSave.recurrence_config
2362
+ ((_d = rootNode.recurrence_config) == null ? void 0 : _d.enabled) ? rootNode.recurrence_config : nodeToSave.recurrence_config
2361
2363
  );
2362
2364
  if (nextDateObj) {
2363
2365
  const currentCounter = sceneDataRef.current.quest_counter || 1;
2364
2366
  const usedCounter = currentCounter;
2365
2367
  const nextCounter = currentCounter + 1;
2366
2368
  sceneDataRef.current.quest_counter = nextCounter;
2367
- let nextName = nodeToSave.raw_title || nodeToSave.name;
2368
- const prefixParts = (nodeToSave.name || "").split(" - \xBB ");
2369
+ let nextName = rootNode.raw_title || rootNode.name;
2370
+ const prefixParts = (rootNode.name || "").split(" - \xBB ");
2369
2371
  const questPrefix = prefixParts.length > 1 ? prefixParts[0] : "";
2370
2372
  if (questPrefix) {
2371
2373
  const baseParts = questPrefix.split(" - ");
2372
2374
  const prefixBase = baseParts[0];
2373
- nextName = `${prefixBase} - ${usedCounter} - \xBB ${nodeToSave.raw_title || prefixParts[1]}`;
2375
+ nextName = `${prefixBase} - ${usedCounter} - \xBB ${rootNode.raw_title || prefixParts[1]}`;
2374
2376
  } else {
2375
- nextName = `${usedCounter} - \xBB ${nodeToSave.raw_title || nodeToSave.name}`;
2377
+ nextName = `${usedCounter} - \xBB ${rootNode.raw_title || rootNode.name}`;
2376
2378
  }
2377
- const nextRecurrenceConfig = { ...nodeToSave.recurrence_config };
2379
+ const nextRecurrenceConfig = {
2380
+ ...rootNode.recurrence_config || nodeToSave.recurrence_config
2381
+ };
2378
2382
  if (nextRecurrenceConfig.type === "custom") {
2379
2383
  nextRecurrenceConfig.custom_date = "";
2380
2384
  }
2381
2385
  const nextQuestNode = {
2382
- ...JSON.parse(JSON.stringify(nodeToSave)),
2386
+ ...JSON.parse(JSON.stringify(rootNode)),
2387
+ // HERANÇA DO ROOT (Template)
2383
2388
  id: import_short_uuid.default.generate(),
2384
2389
  name: nextName,
2385
2390
  status: "Backlog",
2386
2391
  color: "#64748b",
2387
- assignee_id: nodeToSave.recurrence_config.next_assignee_id || "",
2392
+ // ATRIBUIÇÃO LOCAL: Respeita a escolha feita no momento da conclusão da atual
2393
+ assignee_id: ((_e = nodeToSave.recurrence_config) == null ? void 0 : _e.next_assignee_id) || "",
2388
2394
  Date: nextDateObj,
2389
2395
  timeline: [
2390
2396
  {
@@ -2400,15 +2406,47 @@ var userActionHandlers = {
2400
2406
  ],
2401
2407
  version_node: {
2402
2408
  is_version: true,
2403
- parent_node: ((_c = nodeToSave.version_node) == null ? void 0 : _c.parent_node) || nodeToSave.id
2409
+ parent_node: rootId
2404
2410
  },
2405
- reviewStack: (nodeToSave.reviewStack || []).map((r) => ({
2411
+ reviewStack: (rootNode.reviewStack || []).map((r) => ({
2406
2412
  ...r,
2407
2413
  status: "pending"
2408
2414
  })),
2409
2415
  recurrence_config: nextRecurrenceConfig
2410
2416
  };
2411
- const rootId = ((_d = nodeToSave.version_node) == null ? void 0 : _d.parent_node) || nodeToSave.id;
2417
+ if (context.actions.copy_google_doc_action && nextQuestNode.Links) {
2418
+ const links = nextQuestNode.Links;
2419
+ const docLinkIndex = links.findIndex((l) => l.name === "Google docs");
2420
+ if (docLinkIndex !== -1) {
2421
+ const originalUrl = links[docLinkIndex].value;
2422
+ if (originalUrl) {
2423
+ const docIdMatch = originalUrl.match(/\/d\/([a-zA-Z0-9-_]+)/);
2424
+ if (docIdMatch && docIdMatch[1]) {
2425
+ const fileId = docIdMatch[1];
2426
+ const viewFolderId = (_f = sceneDataRef.current) == null ? void 0 : _f.view_google_folder_id;
2427
+ try {
2428
+ const copyRes = await context.actions.copy_google_doc_action(
2429
+ fileId,
2430
+ nextName,
2431
+ viewFolderId
2432
+ );
2433
+ if (copyRes.success && copyRes.link) {
2434
+ nextQuestNode.Links[docLinkIndex].value = copyRes.link;
2435
+ nextQuestNode.timeline.push({
2436
+ id: import_short_uuid.default.generate(),
2437
+ type: "system_note",
2438
+ timestamp: Date.now(),
2439
+ actorId: "system",
2440
+ description: `Documento Google Docs clonado individualmente para esta inst\xE2ncia.`
2441
+ });
2442
+ }
2443
+ } catch (copyErr) {
2444
+ console.warn("Falha ao clonar Google Doc para recorr\xEAncia:", copyErr);
2445
+ }
2446
+ }
2447
+ }
2448
+ }
2449
+ }
2412
2450
  const nextQuestLink = {
2413
2451
  id: `link_${import_short_uuid.default.generate()}`,
2414
2452
  source: rootId,
@@ -2639,6 +2677,13 @@ var MENTION_REGEX = /\[\[MENTION:node:([a-zA-Z0-9\-_]+)\]\]/g;
2639
2677
  var IMAGE_MENTION_REGEX = /\[\[MENTION:image:([^|\]]+)\|?([^\]]*)\]\]/g;
2640
2678
  var LINK_REGEX = /\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/g;
2641
2679
  var UNIQUE_PROP_TYPES = ["links", "images", "date", "documents"];
2680
+ var QUEST_STATUS_COLORS = {
2681
+ Backlog: "#64748b",
2682
+ "In Progress": "#eab308",
2683
+ Review: "#a855f7",
2684
+ Done: "#22c55e"
2685
+ };
2686
+ var QUEST_STATUSES = ["Backlog", "In Progress", "Review", "Done"];
2642
2687
  function createNewCustomProperty(existingProps = []) {
2643
2688
  const usedTypes = new Set(existingProps.map((p) => p.type));
2644
2689
  let nextType = "text";
@@ -2917,7 +2962,8 @@ var IGNORED_KEYS = [
2917
2962
  "milestone_ids",
2918
2963
  "dependency_ids",
2919
2964
  "quest_tree",
2920
- "quest_abstraction_tree"
2965
+ "quest_abstraction_tree",
2966
+ "assignees"
2921
2967
  ];
2922
2968
  function extractCustomPropsFromNode(node) {
2923
2969
  const customPropTypes = node._customPropTypes || {};
@@ -3546,16 +3592,14 @@ function checkCircularDependency(targetId, depIdToAdd, allNodes = []) {
3546
3592
  };
3547
3593
  return hasPath(depIdToAdd, targetId);
3548
3594
  }
3595
+ function checkAllAssigneesDone(assignees) {
3596
+ if (!assignees || !Array.isArray(assignees) || assignees.length === 0)
3597
+ return true;
3598
+ return assignees.every((a) => a.status === "done");
3599
+ }
3549
3600
 
3550
3601
  // src/components/ContextMenu.jsx
3551
3602
  var import_fi = require("react-icons/fi");
3552
- var QUEST_STATUS_COLORS = {
3553
- "Backlog": "#64748b",
3554
- "In Progress": "#eab308",
3555
- "Review": "#a855f7",
3556
- "Done": "#22c55e"
3557
- };
3558
- var QUEST_STATUSES = ["Backlog", "In Progress", "Review", "Done"];
3559
3603
  function ContextMenu({
3560
3604
  data,
3561
3605
  userRole,
@@ -3791,15 +3835,17 @@ function ContextMenu({
3791
3835
  });
3792
3836
  };
3793
3837
  const renderMainView = () => {
3794
- var _a2, _b2, _c, _d, _e, _f, _g, _h;
3838
+ var _a2, _b2, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
3795
3839
  const hasVersions = computedVersions.length > 0;
3796
3840
  const canCreateVersion = ability.can("create", "Versioning");
3797
3841
  const canReadVersion = ability.can("read", "Versioning");
3798
3842
  const shouldShowVersioningBtn = canCreateVersion || canReadVersion && hasVersions;
3799
- const canStartQuest = isCurrentNodeQuest && (((_a2 = data.nodeData) == null ? void 0 : _a2.status) === "Backlog" || !((_b2 = data.nodeData) == null ? void 0 : _b2.status));
3800
- const isQuestActuallyBlocked = canStartQuest && blockedStatus.isBlocked;
3801
- 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";
3802
- return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es R\xE1pidas")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex flex-col gap-1" }, canStartQuest && /* @__PURE__ */ import_react2.default.createElement(
3843
+ 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);
3844
+ const canStartQuest = isCurrentNodeQuest && (((_e = data.nodeData) == null ? void 0 : _e.status) === "Backlog" || !((_f = data.nodeData) == null ? void 0 : _f.status));
3845
+ const canJoinQuest = isCurrentNodeQuest && ((_g = data.nodeData) == null ? void 0 : _g.status) === "In Progress" && !isUserAssignee;
3846
+ const isQuestActuallyBlocked = (canStartQuest || canJoinQuest) && blockedStatus.isBlocked;
3847
+ 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";
3848
+ return /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es R\xE1pidas")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex flex-col gap-1" }, (canStartQuest || canJoinQuest) && /* @__PURE__ */ import_react2.default.createElement(
3803
3849
  "button",
3804
3850
  {
3805
3851
  onClick: () => {
@@ -3810,10 +3856,10 @@ function ContextMenu({
3810
3856
  },
3811
3857
  disabled: isQuestActuallyBlocked,
3812
3858
  className: `${baseButtonClass} ${isQuestActuallyBlocked ? "opacity-50 grayscale cursor-not-allowed group" : ""}`,
3813
- title: isQuestActuallyBlocked ? "Bloqueado por pr\xE9-requisitos pendentes" : "Atribuir a mim e iniciar"
3859
+ title: isQuestActuallyBlocked ? "Bloqueado por pr\xE9-requisitos pendentes" : canJoinQuest ? "Entrar como respons\xE1vel" : "Atribuir a mim e iniciar"
3814
3860
  },
3815
3861
  isQuestActuallyBlocked ? /* @__PURE__ */ import_react2.default.createElement(import_fi.FiLock, { size: 16, className: "text-amber-400/80" }) : /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.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__ */ import_react2.default.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__ */ import_react2.default.createElement("path", { d: "M9 12H4s.55-3.03 2-5c1.62-2.2 5-4 5-4" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M12 15v5s3.03-.55 5-2c2.2-1.62 4-5 4-5" })),
3816
- /* @__PURE__ */ import_react2.default.createElement("span", { className: isQuestActuallyBlocked ? "text-amber-200/60" : "" }, "Iniciar Quest"),
3862
+ /* @__PURE__ */ import_react2.default.createElement("span", { className: isQuestActuallyBlocked ? "text-amber-200/60" : "" }, canJoinQuest ? "Entrar na Quest" : "Iniciar Quest"),
3817
3863
  isQuestActuallyBlocked && /* @__PURE__ */ import_react2.default.createElement(import_fi.FiLock, { className: "ml-auto opacity-0 group-hover:opacity-100 transition-opacity", size: 12 })
3818
3864
  ), canFinishQuest && /* @__PURE__ */ import_react2.default.createElement(
3819
3865
  "button",
@@ -3827,7 +3873,7 @@ function ContextMenu({
3827
3873
  },
3828
3874
  /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("path", { d: "M22 11.08V12a10 10 0 1 1-5.93-9.14" }), /* @__PURE__ */ import_react2.default.createElement("polyline", { points: "22 4 12 14.01 9 11.01" })),
3829
3875
  /* @__PURE__ */ import_react2.default.createElement("span", null, "Finalizar Etapa")
3830
- ), (canStartQuest || canFinishQuest) && /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-1.5" }, /* @__PURE__ */ import_react2.default.createElement("span", { className: "text-[10px] uppercase tracking-wider text-slate-500 font-bold" }, "Prerrequisitos")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex flex-col gap-0.5 px-1 pb-1" }, data.nodeData.dependency_ids.map((depId) => {
3876
+ ), (canStartQuest || canJoinQuest || canFinishQuest) && /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-1.5" }, /* @__PURE__ */ import_react2.default.createElement("span", { className: "text-[10px] uppercase tracking-wider text-slate-500 font-bold" }, "Prerrequisitos")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex flex-col gap-0.5 px-1 pb-1" }, data.nodeData.dependency_ids.map((depId) => {
3831
3877
  const depNode = allParentNodes.find((n) => String(n.id) === String(depId));
3832
3878
  if (!depNode) return null;
3833
3879
  const isPrereqDone = depNode.status === "Done";
@@ -3845,7 +3891,7 @@ function ContextMenu({
3845
3891
  /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: `w-1.5 h-1.5 rounded-full flex-shrink-0 ${isPrereqDone ? "bg-green-500" : "bg-amber-500 animate-pulse"}` }), /* @__PURE__ */ import_react2.default.createElement("span", { className: `truncate ${isPrereqDone ? "text-slate-400" : "text-slate-200 font-medium"}` }, depNode.raw_title || depNode.name)),
3846
3892
  /* @__PURE__ */ import_react2.default.createElement(import_fi.FiChevronRight, { className: "opacity-0 group-hover:opacity-100 transition-opacity text-slate-500", size: 12 })
3847
3893
  );
3848
- })), /* @__PURE__ */ import_react2.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" })), ability.can("create", "Connection") && /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => onStartConnection == null ? void 0 : onStartConnection(data.nodeData), className: baseButtonClass, title: "Conectar" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.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__ */ import_react2.default.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__ */ import_react2.default.createElement("span", null, "Conectar")), ability.can("create", "Node") && !((_h = data.nodeData) == null ? void 0 : _h.is_quest) && /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => onStartCreation == null ? void 0 : onStartCreation(data.nodeData), className: baseButtonClass, title: "Criar e Conectar" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react2.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "16" }), /* @__PURE__ */ import_react2.default.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" })), /* @__PURE__ */ import_react2.default.createElement("span", null, "Criar e Conectar")), ability.can("create", "Ancestry") && /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => onStartAncestryCreation == null ? void 0 : onStartAncestryCreation(data.nodeData), className: baseButtonClass, title: "Criar Ancestralidade" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.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__ */ import_react2.default.createElement("path", { d: "M10 16v-3a2 2 0 0 1 2-2h4" }), /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("path", { d: "M14 8v3a2 2 0 0 0 2 2h4" })), /* @__PURE__ */ import_react2.default.createElement("span", null, "Criar Ancestralidade")), shouldShowVersioningBtn && /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => setMenuView("versioning"), className: baseButtonClass, title: hasVersions ? "Versionamento" : "Criar Versionamento" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("line", { x1: "6", y1: "3", x2: "6", y2: "15" }), /* @__PURE__ */ import_react2.default.createElement("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ import_react2.default.createElement("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })), /* @__PURE__ */ import_react2.default.createElement("span", null, hasVersions || !canCreateVersion ? "Versionamento" : "Criar Versionamento")), (connections.length > 0 || availableAncestries.length > 0) && ability.can("read", "Connection") && /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => setMenuView("connections"), className: baseButtonClass, title: "Conex\xF5es" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.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__ */ import_react2.default.createElement("path", { d: "M8 12h8" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M12 8v8" })), /* @__PURE__ */ import_react2.default.createElement("span", null, "Conex\xF5es (", totalConnectionsCount, ")"))), /* @__PURE__ */ import_react2.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => {
3894
+ })), /* @__PURE__ */ import_react2.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" })), ability.can("create", "Connection") && /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => onStartConnection == null ? void 0 : onStartConnection(data.nodeData), className: baseButtonClass, title: "Conectar" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.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__ */ import_react2.default.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__ */ import_react2.default.createElement("span", null, "Conectar")), ability.can("create", "Node") && !((_n = data.nodeData) == null ? void 0 : _n.is_quest) && /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => onStartCreation == null ? void 0 : onStartCreation(data.nodeData), className: baseButtonClass, title: "Criar e Conectar" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react2.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "16" }), /* @__PURE__ */ import_react2.default.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" })), /* @__PURE__ */ import_react2.default.createElement("span", null, "Criar e Conectar")), ability.can("create", "Ancestry") && /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => onStartAncestryCreation == null ? void 0 : onStartAncestryCreation(data.nodeData), className: baseButtonClass, title: "Criar Ancestralidade" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.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__ */ import_react2.default.createElement("path", { d: "M10 16v-3a2 2 0 0 1 2-2h4" }), /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("path", { d: "M14 8v3a2 2 0 0 0 2 2h4" })), /* @__PURE__ */ import_react2.default.createElement("span", null, "Criar Ancestralidade")), shouldShowVersioningBtn && /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => setMenuView("versioning"), className: baseButtonClass, title: hasVersions ? "Versionamento" : "Criar Versionamento" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("line", { x1: "6", y1: "3", x2: "6", y2: "15" }), /* @__PURE__ */ import_react2.default.createElement("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ import_react2.default.createElement("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })), /* @__PURE__ */ import_react2.default.createElement("span", null, hasVersions || !canCreateVersion ? "Versionamento" : "Criar Versionamento")), (connections.length > 0 || availableAncestries.length > 0) && ability.can("read", "Connection") && /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => setMenuView("connections"), className: baseButtonClass, title: "Conex\xF5es" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.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__ */ import_react2.default.createElement("path", { d: "M8 12h8" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M12 8v8" })), /* @__PURE__ */ import_react2.default.createElement("span", null, "Conex\xF5es (", totalConnectionsCount, ")"))), /* @__PURE__ */ import_react2.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => {
3849
3895
  onFocusNode == null ? void 0 : onFocusNode(data.nodeData);
3850
3896
  onClose();
3851
3897
  }, className: baseButtonClass, title: "Focar na c\xE2mera" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react2.default.createElement("circle", { cx: "12", cy: "12", r: "3" })), /* @__PURE__ */ import_react2.default.createElement("span", null, "Focar neste Node")), /* @__PURE__ */ import_react2.default.createElement("button", { onClick: (e) => handleCopyLink(e, data.nodeData), className: baseButtonClass, title: "Copiar Link para Compartilhar" }, isLinkCopied ? /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("polyline", { points: "20 6 9 17 4 12" })) : /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.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__ */ import_react2.default.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__ */ import_react2.default.createElement("span", { className: isLinkCopied ? "text-green-400" : "" }, isLinkCopied ? "Copiado!" : "Copiar Link")), ability.can("dismiss", "Node") && /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => onDismissNode == null ? void 0 : onDismissNode(data.nodeData), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.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__ */ import_react2.default.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ import_react2.default.createElement("span", null, "Dismiss")), /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => onDismissOtherNodes == null ? void 0 : onDismissOtherNodes(data.nodeData), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ import_react2.default.createElement("span", null, "Dismiss other nodes"))), ability.can("delete", "Node") && /* @__PURE__ */ import_react2.default.createElement("button", { onClick: () => setMenuView("deleteConfirmation"), className: deleteButtonClass, title: "Excluir Node" }, /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ import_react2.default.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ import_react2.default.createElement("span", null, "Excluir Node"))));
@@ -4653,6 +4699,7 @@ function XViewSidebar({
4653
4699
  status: questFilterStatus,
4654
4700
  milestoneId: questFilterMilestone
4655
4701
  });
4702
+ onToggle(false);
4656
4703
  } finally {
4657
4704
  setIsQuestLensLoading(false);
4658
4705
  }
@@ -4717,6 +4764,7 @@ function XViewSidebar({
4717
4764
  centerNodeId: reshapeCenterNodeId
4718
4765
  });
4719
4766
  setActiveSubMenu(null);
4767
+ onToggle(false);
4720
4768
  },
4721
4769
  disabled: reshapeLayoutType === "Star" && !reshapeCenterNodeId,
4722
4770
  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"
@@ -4972,22 +5020,33 @@ function XViewSidebar({
4972
5020
  /* @__PURE__ */ import_react3.default.createElement("polyline", { points: "2 12 12 17 22 12" })
4973
5021
  ),
4974
5022
  "Reshape"
4975
- )), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: onActivateTimeline, className: buttonBaseClass }, /* @__PURE__ */ import_react3.default.createElement(
4976
- "svg",
5023
+ )), /* @__PURE__ */ import_react3.default.createElement(
5024
+ "button",
4977
5025
  {
4978
- xmlns: "http://www.w3.org/2000/svg",
4979
- width: "16",
4980
- height: "16",
4981
- viewBox: "0 0 24 24",
4982
- fill: "none",
4983
- stroke: "currentColor",
4984
- strokeWidth: "2",
4985
- strokeLinecap: "round",
4986
- strokeLinejoin: "round"
5026
+ onClick: () => {
5027
+ onActivateTimeline();
5028
+ onToggle(false);
5029
+ },
5030
+ className: buttonBaseClass
4987
5031
  },
4988
- /* @__PURE__ */ import_react3.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
4989
- /* @__PURE__ */ import_react3.default.createElement("polyline", { points: "12 6 12 12 16 14" })
4990
- ), "Timeline"), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: onOpenBoards, className: buttonBaseClass }, /* @__PURE__ */ import_react3.default.createElement(import_fi2.FiLayers, { size: 16 }), "Boards")), /* @__PURE__ */ import_react3.default.createElement("div", { className: "h-px bg-white/10" }), /* @__PURE__ */ import_react3.default.createElement("section", { className: "space-y-3" }, /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Milestones"), /* @__PURE__ */ import_react3.default.createElement(
5032
+ /* @__PURE__ */ import_react3.default.createElement(
5033
+ "svg",
5034
+ {
5035
+ xmlns: "http://www.w3.org/2000/svg",
5036
+ width: "16",
5037
+ height: "16",
5038
+ viewBox: "0 0 24 24",
5039
+ fill: "none",
5040
+ stroke: "currentColor",
5041
+ strokeWidth: "2",
5042
+ strokeLinecap: "round",
5043
+ strokeLinejoin: "round"
5044
+ },
5045
+ /* @__PURE__ */ import_react3.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
5046
+ /* @__PURE__ */ import_react3.default.createElement("polyline", { points: "12 6 12 12 16 14" })
5047
+ ),
5048
+ "Timeline"
5049
+ ), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: onOpenBoards, className: buttonBaseClass }, /* @__PURE__ */ import_react3.default.createElement(import_fi2.FiLayers, { size: 16 }), "Boards")), /* @__PURE__ */ import_react3.default.createElement("div", { className: "h-px bg-white/10" }), /* @__PURE__ */ import_react3.default.createElement("section", { className: "space-y-3" }, /* @__PURE__ */ import_react3.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Milestones"), /* @__PURE__ */ import_react3.default.createElement(
4991
5050
  "button",
4992
5051
  {
4993
5052
  onClick: onOpenMilestoneManager,
@@ -6550,6 +6609,7 @@ function DescriptionDisplay({
6550
6609
  mentionCount++;
6551
6610
  }
6552
6611
  });
6612
+ console.log("[DescriptionDisplay] flatNavigation computed:", navItems.length, "items", navItems);
6553
6613
  return navItems;
6554
6614
  }, [sections]);
6555
6615
  const [currentStepIndex, setCurrentStepIndex] = (0, import_react7.useState)(0);
@@ -6596,14 +6656,24 @@ function DescriptionDisplay({
6596
6656
  const handleKeyDown = (e) => {
6597
6657
  if (e.target.tagName === "INPUT" || e.target.tagName === "TEXTAREA") return;
6598
6658
  const currentItem = flatNavigation[currentStepIndex];
6659
+ if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)) {
6660
+ console.log(`[DescriptionDisplay] Key pressed: ${e.key}`, {
6661
+ currentStepIndex,
6662
+ flatNavigationLength: flatNavigation.length,
6663
+ currentItem,
6664
+ currentBranchDirection
6665
+ });
6666
+ }
6599
6667
  if (e.key === "ArrowRight") {
6600
6668
  e.preventDefault();
6601
6669
  e.stopPropagation();
6602
6670
  if (currentStepIndex === 0 && currentBranchDirection === "left") {
6671
+ console.log("[DescriptionDisplay] ArrowRight: Navigating back from left branch");
6603
6672
  if (onBranchNav) onBranchNav(null, "back");
6604
6673
  return;
6605
6674
  }
6606
6675
  if (currentItem && currentItem.type === "mention" && onBranchNav) {
6676
+ console.log("[DescriptionDisplay] ArrowRight: Opening right branch for node", currentItem.nodeId);
6607
6677
  onBranchNav(currentItem.nodeId, "open", "right");
6608
6678
  return;
6609
6679
  }
@@ -6612,10 +6682,12 @@ function DescriptionDisplay({
6612
6682
  e.preventDefault();
6613
6683
  e.stopPropagation();
6614
6684
  if (currentStepIndex === 0 && currentBranchDirection === "right") {
6685
+ console.log("[DescriptionDisplay] ArrowLeft: Navigating back from right branch");
6615
6686
  if (onBranchNav) onBranchNav(null, "back");
6616
6687
  return;
6617
6688
  }
6618
6689
  if (currentItem && currentItem.type === "mention" && onBranchNav) {
6690
+ console.log("[DescriptionDisplay] ArrowLeft: Opening left branch for node", currentItem.nodeId);
6619
6691
  onBranchNav(currentItem.nodeId, "open", "left");
6620
6692
  return;
6621
6693
  }
@@ -6623,18 +6695,33 @@ function DescriptionDisplay({
6623
6695
  if (e.key === "ArrowDown") {
6624
6696
  e.preventDefault();
6625
6697
  if (flatNavigation.length > 1) {
6626
- setCurrentStepIndex((prev) => Math.min(prev + 1, flatNavigation.length - 1));
6698
+ setCurrentStepIndex((prev) => {
6699
+ const next = Math.min(prev + 1, flatNavigation.length - 1);
6700
+ console.log(`[DescriptionDisplay] ArrowDown: ${prev} -> ${next}`);
6701
+ return next;
6702
+ });
6627
6703
  }
6628
6704
  }
6629
6705
  if (e.key === "ArrowUp") {
6630
6706
  e.preventDefault();
6631
6707
  if (flatNavigation.length > 1) {
6632
- setCurrentStepIndex((prev) => Math.max(prev - 1, 0));
6708
+ setCurrentStepIndex((prev) => {
6709
+ const next = Math.max(prev - 1, 0);
6710
+ console.log(`[DescriptionDisplay] ArrowUp: ${prev} -> ${next}`);
6711
+ return next;
6712
+ });
6633
6713
  }
6634
6714
  }
6635
6715
  };
6716
+ console.log("[DescriptionDisplay] Attaching keydown listener", {
6717
+ flatNavigationLength: flatNavigation.length,
6718
+ currentStepIndex,
6719
+ currentBranchDirection
6720
+ });
6636
6721
  window.addEventListener("keydown", handleKeyDown);
6637
- return () => window.removeEventListener("keydown", handleKeyDown);
6722
+ return () => {
6723
+ window.removeEventListener("keydown", handleKeyDown);
6724
+ };
6638
6725
  }, [flatNavigation, currentStepIndex, onBranchNav, currentBranchDirection]);
6639
6726
  (0, import_react7.useEffect)(() => {
6640
6727
  if (activeRef.current) {
@@ -8390,7 +8477,7 @@ function CreateAncestryPanel({
8390
8477
  setIsSaving(true);
8391
8478
  const processedSections = processDescriptionForSave(currentInputDesc, currentInputSections);
8392
8479
  setExistingSections(processedSections);
8393
- const updatedRootTree = JSON.parse(JSON.stringify(ancestryMode.tree));
8480
+ const updatedRootTree = applyDescriptionToTree(ancestryMode.tree, currentInputDesc, processedSections);
8394
8481
  const extrasObj = {
8395
8482
  ...toObjectFromCustomProps(customProps.filter((p) => !p.isEditing)),
8396
8483
  is_private: isPrivate
@@ -10650,9 +10737,8 @@ function InSceneQuestForm({
10650
10737
  create_google_doc_action,
10651
10738
  view_google_folder_id
10652
10739
  }) {
10653
- var _a, _b;
10654
10740
  const [name, setName] = (0, import_react19.useState)("");
10655
- const [assigneeId, setAssigneeId] = (0, import_react19.useState)("");
10741
+ const [assigneeIds, setAssigneeIds] = (0, import_react19.useState)([]);
10656
10742
  const [milestoneIds, setMilestoneIds] = (0, import_react19.useState)([]);
10657
10743
  const [types, setTypes] = (0, import_react19.useState)(["quest"]);
10658
10744
  const [typeInput, setTypeInput] = (0, import_react19.useState)("");
@@ -10731,8 +10817,8 @@ function InSceneQuestForm({
10731
10817
  const filteredDependencies = import_react19.default.useMemo(() => {
10732
10818
  const search = dependencyInput.toLowerCase().trim();
10733
10819
  return dependencyQuests.filter((q) => {
10734
- var _a2;
10735
- const nameMatch = ((_a2 = q.name) == null ? void 0 : _a2.toLowerCase().includes(search)) || q.raw_title && q.raw_title.toLowerCase().includes(search);
10820
+ var _a;
10821
+ const nameMatch = ((_a = q.name) == null ? void 0 : _a.toLowerCase().includes(search)) || q.raw_title && q.raw_title.toLowerCase().includes(search);
10736
10822
  const notAlreadyAdded = !dependencyIds.includes(q.id);
10737
10823
  return nameMatch && notAlreadyAdded;
10738
10824
  });
@@ -10824,8 +10910,8 @@ function InSceneQuestForm({
10824
10910
  const newProp = createNewCustomProperty(customProps);
10825
10911
  setCustomProps([...customProps, newProp]);
10826
10912
  setTimeout(() => {
10827
- var _a2;
10828
- (_a2 = propsEndRef.current) == null ? void 0 : _a2.scrollIntoView({
10913
+ var _a;
10914
+ (_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({
10829
10915
  behavior: "smooth",
10830
10916
  block: "center"
10831
10917
  });
@@ -10875,7 +10961,10 @@ function InSceneQuestForm({
10875
10961
  type: types,
10876
10962
  color: QUEST_STATUS_COLORS2[status],
10877
10963
  status,
10878
- assignee_id: assigneeId || null,
10964
+ assignee_id: assigneeIds[0] || null,
10965
+ // Legado: primeiro do array
10966
+ assignees: assigneeIds.map((id) => ({ id, status: "pending" })),
10967
+ // NOVO: Estrutura múltipla
10879
10968
  size,
10880
10969
  intensity,
10881
10970
  description: description.trim(),
@@ -10960,13 +11049,25 @@ function InSceneQuestForm({
10960
11049
  {
10961
11050
  type: "button",
10962
11051
  onClick: () => setIsAssigneeDropdownOpen(!isAssigneeDropdownOpen),
10963
- 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"
11052
+ 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"
10964
11053
  },
10965
- /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react19.default.createElement(import_fi17.FiUser, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ import_react19.default.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")),
11054
+ /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex flex-wrap items-center gap-1.5 min-h-[24px]" }, /* @__PURE__ */ import_react19.default.createElement(import_fi17.FiUser, { className: "text-slate-400 flex-shrink-0", size: 14 }), assigneeIds.length === 0 ? /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-slate-500" }, "Nenhum selecionado") : assigneeIds.map((id) => {
11055
+ const member = viewMembers.find((m) => m.id === id);
11056
+ return /* @__PURE__ */ import_react19.default.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__ */ import_react19.default.createElement(
11057
+ import_fi17.FiX,
11058
+ {
11059
+ className: "hover:text-white cursor-pointer",
11060
+ onClick: (e) => {
11061
+ e.stopPropagation();
11062
+ setAssigneeIds((prev) => prev.filter((aid) => aid !== id));
11063
+ }
11064
+ }
11065
+ ));
11066
+ })),
10966
11067
  /* @__PURE__ */ import_react19.default.createElement(
10967
11068
  import_fi17.FiChevronDown,
10968
11069
  {
10969
- className: `text-slate-400 transition-transform duration-200 ${isAssigneeDropdownOpen ? "rotate-180" : ""}`
11070
+ className: `text-slate-400 flex-shrink-0 transition-transform duration-200 ${isAssigneeDropdownOpen ? "rotate-180" : ""}`
10970
11071
  }
10971
11072
  )
10972
11073
  ), isAssigneeDropdownOpen && /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement(
@@ -10993,13 +11094,13 @@ function InSceneQuestForm({
10993
11094
  "li",
10994
11095
  {
10995
11096
  onClick: () => {
10996
- setAssigneeId("");
11097
+ setAssigneeIds([]);
10997
11098
  setIsAssigneeDropdownOpen(false);
10998
11099
  setAssigneeSearchQuery("");
10999
11100
  },
11000
- 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"}`
11101
+ 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"}`
11001
11102
  },
11002
- "Nenhum"
11103
+ "Limpar sele\xE7\xE3o"
11003
11104
  ), viewMembers.filter((member) => {
11004
11105
  const search = assigneeSearchQuery.toLowerCase();
11005
11106
  return (member.name || "").toLowerCase().includes(search) || (member.email || "").toLowerCase().includes(search);
@@ -11008,13 +11109,16 @@ function InSceneQuestForm({
11008
11109
  {
11009
11110
  key: member.id,
11010
11111
  onClick: () => {
11011
- setAssigneeId(member.id);
11112
+ setAssigneeIds(
11113
+ (prev) => prev.includes(member.id) ? prev.filter((id) => id !== member.id) : [...prev, member.id]
11114
+ );
11012
11115
  setIsAssigneeDropdownOpen(false);
11013
11116
  setAssigneeSearchQuery("");
11014
11117
  },
11015
- 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"}`
11118
+ 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"}`
11016
11119
  },
11017
- member.name || member.email || member.id
11120
+ /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center gap-2" }, member.name || member.email || member.id),
11121
+ assigneeIds.includes(member.id) && /* @__PURE__ */ import_react19.default.createElement(import_fi17.FiCheck, { className: "text-indigo-400" })
11018
11122
  )), viewMembers.filter((member) => {
11019
11123
  const search = assigneeSearchQuery.toLowerCase();
11020
11124
  return (member.name || "").toLowerCase().includes(search) || (member.email || "").toLowerCase().includes(search);
@@ -12178,12 +12282,6 @@ function QuestTimeline({
12178
12282
 
12179
12283
  // src/components/QuestDetailsPanel.jsx
12180
12284
  var import_ai4 = require("react-icons/ai");
12181
- var QUEST_STATUS_COLORS3 = {
12182
- "Backlog": "#64748b",
12183
- "In Progress": "#eab308",
12184
- "Review": "#a855f7",
12185
- "Done": "#22c55e"
12186
- };
12187
12285
  function QuestDetailsPanel({
12188
12286
  node,
12189
12287
  onClose,
@@ -12225,6 +12323,7 @@ function QuestDetailsPanel({
12225
12323
  const [status, setStatus] = (0, import_react22.useState)((node == null ? void 0 : node.status) ?? "Backlog");
12226
12324
  const [size, setSize] = (0, import_react22.useState)((node == null ? void 0 : node.size) ?? "medium");
12227
12325
  const [assigneeId, setAssigneeId] = (0, import_react22.useState)((node == null ? void 0 : node.assignee_id) || "");
12326
+ const [assignees, setAssignees] = (0, import_react22.useState)((node == null ? void 0 : node.assignees) || []);
12228
12327
  const [description, setDescription] = (0, import_react22.useState)((node == null ? void 0 : node.description) ?? "");
12229
12328
  const [intensity, setIntensity] = (0, import_react22.useState)((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
12230
12329
  const [milestoneIds, setMilestoneIds] = (0, import_react22.useState)((node == null ? void 0 : node.milestone_ids) || []);
@@ -12377,6 +12476,7 @@ function QuestDetailsPanel({
12377
12476
  setStatus((node == null ? void 0 : node.status) ?? "Backlog");
12378
12477
  setSize((node == null ? void 0 : node.size) ?? "medium");
12379
12478
  setAssigneeId((node == null ? void 0 : node.assignee_id) || "");
12479
+ setAssignees((node == null ? void 0 : node.assignees) || []);
12380
12480
  setReturnAssigneeId("");
12381
12481
  setDescription((node == null ? void 0 : node.description) ?? "");
12382
12482
  setIntensity((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
@@ -12577,19 +12677,22 @@ ${noteText}` : noteText : entry.notes,
12577
12677
  const updateImageInNote = (id, val) => {
12578
12678
  setNoteImages(noteImages.map((img) => img.id === id ? { ...img, value: val } : img));
12579
12679
  };
12580
- const handleStatusChange = (newStatus) => {
12680
+ const handleStatusChange = (newStatus, overrides = {}) => {
12581
12681
  setStatus(newStatus);
12582
- const newColor = QUEST_STATUS_COLORS3[newStatus];
12682
+ const newColor = QUEST_STATUS_COLORS[newStatus];
12583
12683
  const actorId = (currentUser == null ? void 0 : currentUser.id) || "unknown";
12584
- const currentAssignee = viewMembers.find((m) => String(m.id) === String(assigneeId));
12585
- const assigneeName = (currentAssignee == null ? void 0 : currentAssignee.name) || (currentAssignee == null ? void 0 : currentAssignee.email) || "Nenhum";
12684
+ const currentAssigneeIds = overrides.assignees || assignees;
12685
+ const assigneeNames = currentAssigneeIds.map((a) => {
12686
+ var _a2;
12687
+ return ((_a2 = viewMembers.find((m) => m.id === a.id)) == null ? void 0 : _a2.name) || "Membro";
12688
+ }).join(", ");
12586
12689
  const newEvent = createTimelineEntry(
12587
12690
  actorId,
12588
- `Status "${newStatus}" - Respons\xE1vel: ${assigneeName}`,
12691
+ `Status "${newStatus}" - Respons\xE1veis: ${assigneeNames || "Nenhum"}`,
12589
12692
  "status_changed",
12590
- { metadata: { to_assignee_id: assigneeId } }
12693
+ { metadata: { to_status: newStatus } }
12591
12694
  );
12592
- const newTimeline = [...timeline, newEvent];
12695
+ const newTimeline = [...overrides.timeline || timeline, newEvent];
12593
12696
  setTimeline(newTimeline);
12594
12697
  onColorChange == null ? void 0 : onColorChange(node.id, newColor);
12595
12698
  onDataUpdate == null ? void 0 : onDataUpdate({
@@ -12597,10 +12700,12 @@ ${noteText}` : noteText : entry.notes,
12597
12700
  status: newStatus,
12598
12701
  color: newColor,
12599
12702
  timeline: newTimeline,
12703
+ assignees: currentAssigneeIds,
12600
12704
  Date: questDate,
12601
12705
  recurrence_config: recurrenceConfig
12602
12706
  });
12603
12707
  setHasUnsavedChanges(true);
12708
+ triggerAutoSave({ status: newStatus, timeline: newTimeline, assignees: currentAssigneeIds });
12604
12709
  };
12605
12710
  const handleAddType = (newType) => {
12606
12711
  const trimmed = newType.trim();
@@ -12717,6 +12822,7 @@ ${noteText}` : noteText : entry.notes,
12717
12822
  const currentStandardName = questPrefix ? `${questPrefix} - \xBB ${currentRawTitle || "Sem t\xEDtulo"}` : currentRawTitle;
12718
12823
  const currentTypes = overrides.types !== void 0 ? overrides.types : types;
12719
12824
  const currentAssigneeId = overrides.assigneeId !== void 0 ? overrides.assigneeId : assigneeId;
12825
+ const currentAssignees = overrides.assignees !== void 0 ? overrides.assignees : assignees;
12720
12826
  const currentDescription = overrides.description !== void 0 ? overrides.description : description;
12721
12827
  const currentCustomProps = overrides.customProps !== void 0 ? overrides.customProps : customProps;
12722
12828
  const currentReviewStack = overrides.reviewStack !== void 0 ? overrides.reviewStack : reviewStack;
@@ -12743,9 +12849,10 @@ ${noteText}` : noteText : entry.notes,
12743
12849
  raw_title: currentRawTitle.trim(),
12744
12850
  // Salva o título simples
12745
12851
  type: currentTypes,
12746
- color: QUEST_STATUS_COLORS3[currentStatus],
12852
+ color: QUEST_STATUS_COLORS[currentStatus],
12747
12853
  status: currentStatus,
12748
12854
  assignee_id: currentAssigneeId || null,
12855
+ assignees: currentAssignees,
12749
12856
  size,
12750
12857
  description: currentDescription.trim(),
12751
12858
  description_sections: processedSections,
@@ -12775,6 +12882,19 @@ ${noteText}` : noteText : entry.notes,
12775
12882
  const triggerAutoSave = (overrides = {}) => {
12776
12883
  handleSave(true, overrides);
12777
12884
  };
12885
+ const handleToggleAssignee = (memberId) => {
12886
+ var _a2;
12887
+ const isAlreadyAssignee = assignees.some((a) => a.id === memberId);
12888
+ let updatedAssignees;
12889
+ if (isAlreadyAssignee) {
12890
+ updatedAssignees = assignees.filter((a) => a.id !== memberId);
12891
+ } else {
12892
+ updatedAssignees = [...assignees, { id: memberId, status: "pending" }];
12893
+ }
12894
+ setAssignees(updatedAssignees);
12895
+ setAssigneeId(((_a2 = updatedAssignees[0]) == null ? void 0 : _a2.id) || "");
12896
+ setHasUnsavedChanges(true);
12897
+ };
12778
12898
  const handleCancel = () => {
12779
12899
  if (node) {
12780
12900
  onNameChange == null ? void 0 : onNameChange(node.id, node.name);
@@ -12832,16 +12952,41 @@ ${noteText}` : noteText : entry.notes,
12832
12952
  onImageClick: handleImageClickFromText,
12833
12953
  onSaveDescription: handleSaveDescriptionInline
12834
12954
  }
12835
- ) : /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, /* @__PURE__ */ import_react22.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS3[status]}, transparent)` } }), /* @__PURE__ */ import_react22.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ import_react22.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Quest"), /* @__PURE__ */ import_react22.default.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__ */ import_react22.default.createElement(import_fi20.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiLink, { size: 12 }))), /* @__PURE__ */ import_react22.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, standardizedName || (node == null ? void 0 : node.name))), /* @__PURE__ */ import_react22.default.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__ */ import_react22.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react22.default.createElement("label", { className: "text-xs text-slate-300" }, "Assignee (Respons\xE1vel)"), canEdit ? /* @__PURE__ */ import_react22.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react22.default.createElement(
12955
+ ) : /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, /* @__PURE__ */ import_react22.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS[status]}, transparent)` } }), /* @__PURE__ */ import_react22.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ import_react22.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Quest"), /* @__PURE__ */ import_react22.default.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__ */ import_react22.default.createElement(import_fi20.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiLink, { size: 12 }))), /* @__PURE__ */ import_react22.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, standardizedName || (node == null ? void 0 : node.name))), /* @__PURE__ */ import_react22.default.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__ */ import_react22.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react22.default.createElement("label", { className: "text-xs text-slate-300" }, "Assignee (Respons\xE1vel)"), canEdit ? /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex flex-col gap-2" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex flex-wrap gap-2" }, assignees.map((a) => {
12956
+ const member = viewMembers.find((m) => m.id === a.id);
12957
+ const isMe = String(a.id) === String(currentUser == null ? void 0 : currentUser.id);
12958
+ return /* @__PURE__ */ import_react22.default.createElement(
12959
+ "div",
12960
+ {
12961
+ key: a.id,
12962
+ 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"}`
12963
+ },
12964
+ /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiUser, { size: 12, className: a.status === "done" ? "text-green-400" : "text-slate-400" }),
12965
+ /* @__PURE__ */ import_react22.default.createElement("span", { className: "text-xs font-medium" }, (member == null ? void 0 : member.name) || (member == null ? void 0 : member.email) || "Membro", isMe && " (Voc\xEA)"),
12966
+ a.status === "done" && /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiCheck, { size: 12 }),
12967
+ canEdit && /* @__PURE__ */ import_react22.default.createElement(
12968
+ "button",
12969
+ {
12970
+ onClick: (e) => {
12971
+ e.stopPropagation();
12972
+ handleToggleAssignee(a.id);
12973
+ },
12974
+ className: "ml-1 p-0.5 hover:bg-white/10 rounded transition-colors text-slate-400 hover:text-red-400",
12975
+ title: "Remover respons\xE1vel"
12976
+ },
12977
+ /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiX, { size: 12 })
12978
+ )
12979
+ );
12980
+ }), canEdit && /* @__PURE__ */ import_react22.default.createElement(
12836
12981
  "button",
12837
12982
  {
12838
12983
  type: "button",
12839
12984
  onClick: () => setIsAssigneeDropdownOpen(!isAssigneeDropdownOpen),
12840
- 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"
12985
+ 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"
12841
12986
  },
12842
- /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiUser, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ import_react22.default.createElement("span", { className: "text-slate-200 font-medium" }, isAssigneeUndefined ? "Undefined" : (assigneeMember == null ? void 0 : assigneeMember.name) || (assigneeMember == null ? void 0 : assigneeMember.email) || "Nenhum")),
12843
- /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiChevronDown, { className: `text-slate-400 transition-transform duration-200 ${isAssigneeDropdownOpen ? "rotate-180" : ""}` })
12844
- ), isAssigneeDropdownOpen && /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, /* @__PURE__ */ import_react22.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => {
12987
+ /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiPlus, { size: 12 }),
12988
+ "Adicionar Respons\xE1vel"
12989
+ ))), isAssigneeDropdownOpen && /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, /* @__PURE__ */ import_react22.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => {
12845
12990
  setIsAssigneeDropdownOpen(false);
12846
12991
  setAssigneeSearchQuery("");
12847
12992
  } }), /* @__PURE__ */ import_react22.default.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__ */ import_react22.default.createElement("div", { className: "p-2 border-b border-white/5 bg-white/5 flex items-center gap-2" }, /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiSearch, { className: "text-slate-500", size: 14 }), /* @__PURE__ */ import_react22.default.createElement(
@@ -12855,25 +13000,23 @@ ${noteText}` : noteText : entry.notes,
12855
13000
  className: "bg-transparent border-none outline-none text-xs text-white placeholder-slate-500 w-full",
12856
13001
  onClick: (e) => e.stopPropagation()
12857
13002
  }
12858
- )), /* @__PURE__ */ import_react22.default.createElement("ul", { className: "max-h-48 overflow-y-auto custom-scrollbar" }, /* @__PURE__ */ import_react22.default.createElement(
13003
+ )), /* @__PURE__ */ import_react22.default.createElement("ul", { className: "max-h-48 overflow-y-auto custom-scrollbar" }, viewMembers.filter((member) => {
13004
+ const search = assigneeSearchQuery.toLowerCase();
13005
+ const isNotAlreadyAssignee = !assignees.some((a) => a.id === member.id);
13006
+ return isNotAlreadyAssignee && ((member.name || "").toLowerCase().includes(search) || (member.email || "").toLowerCase().includes(search));
13007
+ }).map((member) => /* @__PURE__ */ import_react22.default.createElement(
12859
13008
  "li",
12860
13009
  {
13010
+ key: member.id,
12861
13011
  onClick: () => {
12862
- setAssigneeId("");
12863
- const newTimeline = [...timeline, createTimelineEntry(
12864
- (currentUser == null ? void 0 : currentUser.id) || "unknown",
12865
- `Status "${status}" - Respons\xE1vel: Nenhum`,
12866
- "status_changed"
12867
- )];
12868
- setTimeline(newTimeline);
12869
- setHasUnsavedChanges(true);
13012
+ handleToggleAssignee(member.id);
12870
13013
  setIsAssigneeDropdownOpen(false);
12871
13014
  setAssigneeSearchQuery("");
12872
13015
  },
12873
- 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"}`
13016
+ 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"
12874
13017
  },
12875
- "Nenhum"
12876
- ), isAssigneeUndefined && /* @__PURE__ */ import_react22.default.createElement(
13018
+ member.name || member.email || member.id
13019
+ )), isAssigneeUndefined && /* @__PURE__ */ import_react22.default.createElement(
12877
13020
  "li",
12878
13021
  {
12879
13022
  onClick: () => {
@@ -12885,27 +13028,12 @@ ${noteText}` : noteText : entry.notes,
12885
13028
  "Undefined (Removido)"
12886
13029
  ), viewMembers.filter((member) => {
12887
13030
  const search = assigneeSearchQuery.toLowerCase();
12888
- return (member.name || "").toLowerCase().includes(search) || (member.email || "").toLowerCase().includes(search);
12889
- }).map((member) => /* @__PURE__ */ import_react22.default.createElement(
12890
- "li",
12891
- {
12892
- key: member.id,
12893
- onClick: () => {
12894
- setAssigneeId(member.id);
12895
- const newTimeline = [...timeline, createTimelineEntry(
12896
- (currentUser == null ? void 0 : currentUser.id) || "unknown",
12897
- `Status "${status}" - Respons\xE1vel: ${member.name || member.email}`,
12898
- "status_changed"
12899
- )];
12900
- setTimeline(newTimeline);
12901
- setHasUnsavedChanges(true);
12902
- setIsAssigneeDropdownOpen(false);
12903
- setAssigneeSearchQuery("");
12904
- },
12905
- 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"}`
12906
- },
12907
- member.name || member.email || member.id
12908
- )))))) : /* @__PURE__ */ import_react22.default.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__ */ import_react22.default.createElement(import_fi20.FiUser, { className: "opacity-50", size: 14 }), assigneeId ? assigneeMember ? assigneeMember.name || assigneeMember.email : "Undefined" : "Nenhum")), /* @__PURE__ */ import_react22.default.createElement("div", { className: "space-y-3 pt-4 border-t border-white/5" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiGitBranch, { className: "text-indigo-400", size: 14 }), /* @__PURE__ */ import_react22.default.createElement("h3", { className: "text-[11px] uppercase font-bold text-slate-500 tracking-wider" }, "Estruturas Visuais"))), /* @__PURE__ */ import_react22.default.createElement("div", { className: "bg-slate-900/60 p-2 rounded-xl border border-white/10 flex flex-col gap-2" }, /* @__PURE__ */ import_react22.default.createElement(
13031
+ const isNotAlreadyAssignee = !assignees.some((a) => a.id === member.id);
13032
+ return isNotAlreadyAssignee && ((member.name || "").toLowerCase().includes(search) || (member.email || "").toLowerCase().includes(search));
13033
+ }).length === 0 && /* @__PURE__ */ import_react22.default.createElement("li", { className: "px-3 py-4 text-xs text-slate-500 text-center italic" }, "Nenhum membro dispon\xEDvel"))))) : /* @__PURE__ */ import_react22.default.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__ */ import_react22.default.createElement(import_fi20.FiUser, { className: "opacity-50", size: 14 }), assignees.length > 0 ? assignees.map((a) => {
13034
+ const member = viewMembers.find((m) => m.id === a.id);
13035
+ return /* @__PURE__ */ import_react22.default.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)");
13036
+ }) : "Nenhum")), /* @__PURE__ */ import_react22.default.createElement("div", { className: "space-y-3 pt-4 border-t border-white/5" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiGitBranch, { className: "text-indigo-400", size: 14 }), /* @__PURE__ */ import_react22.default.createElement("h3", { className: "text-[11px] uppercase font-bold text-slate-500 tracking-wider" }, "Estruturas Visuais"))), /* @__PURE__ */ import_react22.default.createElement("div", { className: "bg-slate-900/60 p-2 rounded-xl border border-white/10 flex flex-col gap-2" }, /* @__PURE__ */ import_react22.default.createElement(
12909
13037
  "button",
12910
13038
  {
12911
13039
  type: "button",
@@ -13174,9 +13302,9 @@ ${noteText}` : noteText : entry.notes,
13174
13302
  disabled: !canEdit,
13175
13303
  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"}`
13176
13304
  },
13177
- /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react22.default.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__ */ import_react22.default.createElement("span", { className: "text-slate-200 font-medium" }, status)),
13305
+ /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react22.default.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__ */ import_react22.default.createElement("span", { className: "text-slate-200 font-medium" }, status)),
13178
13306
  canEdit && /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiChevronDown, { className: `text-slate-400 transition-transform duration-200 ${isStatusDropdownOpen ? "rotate-180" : ""}` })
13179
- ), isStatusDropdownOpen && canEdit && /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, /* @__PURE__ */ import_react22.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ import_react22.default.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) => {
13307
+ ), isStatusDropdownOpen && canEdit && /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, /* @__PURE__ */ import_react22.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ import_react22.default.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) => {
13180
13308
  const isBacklog = s === "Backlog";
13181
13309
  const isDisabled = !isBacklog && blockedStatus.isBlocked;
13182
13310
  return /* @__PURE__ */ import_react22.default.createElement(
@@ -13192,7 +13320,7 @@ ${noteText}` : noteText : entry.notes,
13192
13320
  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"}`,
13193
13321
  title: isDisabled ? `Bloqueado por depend\xEAncias: ${blockedStatus.pendingDependencies.map((d) => d.raw_title || d.name).join(", ")}` : ""
13194
13322
  },
13195
- /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react22.default.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS3[s] } }), s),
13323
+ /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react22.default.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS[s] } }), s),
13196
13324
  isDisabled && /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiRepeat, { className: "text-amber-400/60 rotate-180", size: 12 })
13197
13325
  );
13198
13326
  }))))), /* @__PURE__ */ import_react22.default.createElement("div", { className: "pt-4 border-t border-white/5 mt-2" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center justify-between mb-3" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react22.default.createElement(import_fi20.FiRepeat, { className: `w-3.5 h-3.5 ${recurrenceConfig.enabled ? "text-indigo-400" : "text-slate-500"}` }), /* @__PURE__ */ import_react22.default.createElement("span", { className: "text-xs text-slate-300 font-medium uppercase tracking-wider" }, "Recorr\xEAncia")), /* @__PURE__ */ import_react22.default.createElement(
@@ -15580,7 +15708,6 @@ var TIMELINE_INTERVAL_BAR_OPACITY = 0.85;
15580
15708
  var TIMELINE_GOLD_COLOR = 16766720;
15581
15709
  var QUEST_LENS_COLUMN_SPACING = 80;
15582
15710
  var QUEST_LENS_ROW_SPACING = 40;
15583
- var QUEST_STATUS_ORDER = ["Backlog", "In Progress", "Review", "Done"];
15584
15711
  var getAllNodeIdsFromTree = (treeNode) => {
15585
15712
  const ids = /* @__PURE__ */ new Set();
15586
15713
  function traverse(node) {
@@ -15633,6 +15760,7 @@ function XViewScene({
15633
15760
  check_user_permission,
15634
15761
  get_view_members,
15635
15762
  create_google_doc_action,
15763
+ copy_google_doc_action,
15636
15764
  open_google_picker_action,
15637
15765
  upsert_quest_firestore,
15638
15766
  delete_quest_firestore,
@@ -16811,13 +16939,13 @@ function XViewScene({
16811
16939
  sortedTimePoints.forEach((ms, idx) => {
16812
16940
  timeToYMap.set(ms, idx * TIMELINE_LAYER_SPACING_Y);
16813
16941
  });
16814
- const startX = -((QUEST_STATUS_ORDER.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
16942
+ const startX = -((QUEST_STATUSES.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
16815
16943
  let sumX = 0;
16816
16944
  let sumY = 0;
16817
16945
  let questCount = 0;
16818
16946
  const positionGroups = /* @__PURE__ */ new Map();
16819
16947
  const NODE_X_GAP = 22;
16820
- QUEST_STATUS_ORDER.forEach((statusName) => {
16948
+ QUEST_STATUSES.forEach((statusName) => {
16821
16949
  const questsInCol = questsByStatus[statusName];
16822
16950
  questsInCol.forEach((q, rowIndex) => {
16823
16951
  const timeInfo = questTimeInfos.get(String(q.id)) || {
@@ -16898,7 +17026,7 @@ function XViewScene({
16898
17026
  }
16899
17027
  }
16900
17028
  });
16901
- QUEST_STATUS_ORDER.forEach((statusName, colIndex) => {
17029
+ QUEST_STATUSES.forEach((statusName, colIndex) => {
16902
17030
  if (status2 && status2 !== statusName) return;
16903
17031
  const questsInCol = questsByStatus[statusName];
16904
17032
  const colX = startX + colIndex * QUEST_LENS_COLUMN_SPACING;
@@ -17747,19 +17875,6 @@ function XViewScene({
17747
17875
  const dirX = (keysPressed["ArrowRight"] ? 1 : 0) - (keysPressed["ArrowLeft"] ? 1 : 0);
17748
17876
  const dirY = (keysPressed["ArrowUp"] ? 1 : 0) - (keysPressed["ArrowDown"] ? 1 : 0);
17749
17877
  if (isCtrl && (dirX !== 0 || dirY !== 0)) {
17750
- const offset = sceneCamera.position.clone().sub(sceneControls.target);
17751
- const spherical = new THREE3.Spherical().setFromVector3(offset);
17752
- spherical.theta += dirX * rotateSpeed;
17753
- spherical.phi -= dirY * rotateSpeed;
17754
- spherical.makeSafe();
17755
- offset.setFromSpherical(spherical);
17756
- sceneCamera.position.copy(sceneControls.target).add(offset);
17757
- } else if (isShift && dirY !== 0) {
17758
- const factor = keysPressed["ArrowUp"] ? zoomInFactor : zoomOutFactor;
17759
- const offset = sceneCamera.position.clone().sub(sceneControls.target);
17760
- offset.multiplyScalar(factor);
17761
- sceneCamera.position.copy(sceneControls.target).add(offset);
17762
- } else if (!isCtrl && !isShift && (dirX !== 0 || dirY !== 0)) {
17763
17878
  const distance = sceneCamera.position.distanceTo(
17764
17879
  sceneControls.target
17765
17880
  );
@@ -17776,6 +17891,19 @@ function XViewScene({
17776
17891
  vecY.multiplyScalar(dirY * currentPanSpeed);
17777
17892
  sceneCamera.position.add(vecX).add(vecY);
17778
17893
  sceneControls.target.add(vecX).add(vecY);
17894
+ } else if (isShift && dirY !== 0) {
17895
+ const factor = keysPressed["ArrowUp"] ? zoomInFactor : zoomOutFactor;
17896
+ const offset = sceneCamera.position.clone().sub(sceneControls.target);
17897
+ offset.multiplyScalar(factor);
17898
+ sceneCamera.position.copy(sceneControls.target).add(offset);
17899
+ } else if (!isCtrl && !isShift && (dirX !== 0 || dirY !== 0)) {
17900
+ const offset = sceneCamera.position.clone().sub(sceneControls.target);
17901
+ const spherical = new THREE3.Spherical().setFromVector3(offset);
17902
+ spherical.theta += dirX * rotateSpeed;
17903
+ spherical.phi -= dirY * rotateSpeed;
17904
+ spherical.makeSafe();
17905
+ offset.setFromSpherical(spherical);
17906
+ sceneCamera.position.copy(sceneControls.target).add(offset);
17779
17907
  }
17780
17908
  }
17781
17909
  stateRef.current.controls.update();
@@ -18150,7 +18278,8 @@ function XViewScene({
18150
18278
  upsert_quest_link_firestore,
18151
18279
  delete_quest_link_firestore,
18152
18280
  upsert_milestone_firestore,
18153
- update_view_counter
18281
+ update_view_counter,
18282
+ copy_google_doc_action
18154
18283
  }
18155
18284
  };
18156
18285
  },
@@ -18175,7 +18304,8 @@ function XViewScene({
18175
18304
  upsert_quest_link_firestore,
18176
18305
  delete_quest_link_firestore,
18177
18306
  upsert_milestone_firestore,
18178
- update_view_counter
18307
+ update_view_counter,
18308
+ copy_google_doc_action
18179
18309
  ]
18180
18310
  );
18181
18311
  const handleStartVersioning = (nodeData) => {
@@ -18183,7 +18313,7 @@ function XViewScene({
18183
18313
  };
18184
18314
  const handleStartQuestQuick = (0, import_react33.useCallback)(
18185
18315
  (questNode) => {
18186
- var _a2, _b2, _c2;
18316
+ var _a2, _b2, _c2, _d2, _e2, _f2;
18187
18317
  if (!questNode || !actionHandlerContext) return;
18188
18318
  const allParentNodes = Object.values(parentDataRef.current).flatMap(
18189
18319
  (fileData) => fileData.nodes || []
@@ -18204,19 +18334,29 @@ function XViewScene({
18204
18334
  timelineEndLabel,
18205
18335
  ...cleanQuestNode
18206
18336
  } = questNode;
18337
+ let updatedAssignees = [...cleanQuestNode.assignees || []];
18338
+ const isJoining = cleanQuestNode.status === "In Progress";
18339
+ const alreadyIn = updatedAssignees.some((a) => {
18340
+ var _a3;
18341
+ return String(a.id) === String((_a3 = session == null ? void 0 : session.user) == null ? void 0 : _a3.id);
18342
+ });
18343
+ if (!alreadyIn) {
18344
+ updatedAssignees.push({ id: (_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id, status: "pending" });
18345
+ }
18207
18346
  const newTimeline = [
18208
18347
  ...cleanQuestNode.timeline || [],
18209
18348
  createTimelineEntry(
18210
- ((_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id) || "unknown",
18211
- `Status "In Progress" - Respons\xE1vel: ${((_b2 = session == null ? void 0 : session.user) == null ? void 0 : _b2.name) || "usu\xE1rio"}`,
18212
- "status_changed"
18349
+ ((_b2 = session == null ? void 0 : session.user) == null ? void 0 : _b2.id) || "unknown",
18350
+ 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"}`,
18351
+ isJoining ? "assignee_added" : "status_changed"
18213
18352
  )
18214
18353
  ];
18215
18354
  const updatedNode = {
18216
18355
  ...cleanQuestNode,
18217
18356
  status: "In Progress",
18218
18357
  color: "#eab308",
18219
- assignee_id: (_c2 = session == null ? void 0 : session.user) == null ? void 0 : _c2.id,
18358
+ assignee_id: ((_e2 = updatedAssignees[0]) == null ? void 0 : _e2.id) || ((_f2 = session == null ? void 0 : session.user) == null ? void 0 : _f2.id),
18359
+ assignees: updatedAssignees,
18220
18360
  timeline: newTimeline
18221
18361
  };
18222
18362
  if (userActionHandlers.handleSaveNodeDetails) {
@@ -18232,7 +18372,7 @@ function XViewScene({
18232
18372
  );
18233
18373
  const handleFinishQuestQuick = (0, import_react33.useCallback)(
18234
18374
  (questNode) => {
18235
- var _a2, _b2, _c2, _d2;
18375
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2;
18236
18376
  if (!questNode || !actionHandlerContext) return;
18237
18377
  const {
18238
18378
  labelObject,
@@ -18243,7 +18383,44 @@ function XViewScene({
18243
18383
  timelineEndLabel,
18244
18384
  ...cleanQuestNode
18245
18385
  } = questNode;
18246
- let nextAssigneeId = cleanQuestNode.assignee_id;
18386
+ let updatedAssignees = [...cleanQuestNode.assignees || []];
18387
+ if (updatedAssignees.length === 0 && cleanQuestNode.assignee_id) {
18388
+ updatedAssignees = [{ id: cleanQuestNode.assignee_id, status: cleanQuestNode.status === "Done" ? "done" : "pending" }];
18389
+ }
18390
+ const isAssignee = updatedAssignees.some((a) => {
18391
+ var _a3;
18392
+ return String(a.id) === String((_a3 = session == null ? void 0 : session.user) == null ? void 0 : _a3.id);
18393
+ });
18394
+ if (isAssignee) {
18395
+ updatedAssignees = updatedAssignees.map(
18396
+ (a) => {
18397
+ var _a3;
18398
+ 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;
18399
+ }
18400
+ );
18401
+ }
18402
+ const allDone = checkAllAssigneesDone(updatedAssignees);
18403
+ if (!allDone) {
18404
+ const newTimeline2 = [
18405
+ ...cleanQuestNode.timeline || [],
18406
+ createTimelineEntry(
18407
+ ((_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id) || "unknown",
18408
+ `${((_b2 = session == null ? void 0 : session.user) == null ? void 0 : _b2.name) || "Usu\xE1rio"} concluiu sua etapa individual.`,
18409
+ "comment"
18410
+ )
18411
+ ];
18412
+ const updatedNode2 = {
18413
+ ...cleanQuestNode,
18414
+ assignees: updatedAssignees,
18415
+ timeline: newTimeline2
18416
+ };
18417
+ if (userActionHandlers.handleSaveNodeDetails) {
18418
+ userActionHandlers.handleSaveNodeDetails(actionHandlerContext, updatedNode2, true);
18419
+ }
18420
+ setDetailsNode(updatedNode2);
18421
+ return;
18422
+ }
18423
+ let nextAssigneeId = ((_c2 = updatedAssignees[0]) == null ? void 0 : _c2.id) || cleanQuestNode.assignee_id;
18247
18424
  let nextStatus = "Done";
18248
18425
  let newTimeline = [...cleanQuestNode.timeline || []];
18249
18426
  const reviewStack = [...cleanQuestNode.reviewStack || []];
@@ -18274,7 +18451,7 @@ function XViewScene({
18274
18451
  nextStatus = "Done";
18275
18452
  }
18276
18453
  if (nextStatus === "Review") {
18277
- const nextReviewerName = ((_a2 = viewMembers.find((m) => m.id === nextAssigneeId)) == null ? void 0 : _a2.name) || "revisor";
18454
+ const nextReviewerName = ((_d2 = viewMembers.find((m) => m.id === nextAssigneeId)) == null ? void 0 : _d2.name) || "revisor";
18278
18455
  newTimeline.push(
18279
18456
  createTimelineEntry(
18280
18457
  "system",
@@ -18284,15 +18461,15 @@ function XViewScene({
18284
18461
  )
18285
18462
  );
18286
18463
  } else if (nextStatus === "Done") {
18287
- const finisherName = ((_b2 = viewMembers.find(
18464
+ const finisherName = ((_e2 = viewMembers.find(
18288
18465
  (m) => {
18289
18466
  var _a3;
18290
18467
  return m.id === (((_a3 = session == null ? void 0 : session.user) == null ? void 0 : _a3.id) || cleanQuestNode.assignee_id);
18291
18468
  }
18292
- )) == null ? void 0 : _b2.name) || ((_c2 = session == null ? void 0 : session.user) == null ? void 0 : _c2.name) || "respons\xE1vel";
18469
+ )) == null ? void 0 : _e2.name) || ((_f2 = session == null ? void 0 : session.user) == null ? void 0 : _f2.name) || "respons\xE1vel";
18293
18470
  newTimeline.push(
18294
18471
  createTimelineEntry(
18295
- ((_d2 = session == null ? void 0 : session.user) == null ? void 0 : _d2.id) || cleanQuestNode.assignee_id,
18472
+ ((_g2 = session == null ? void 0 : session.user) == null ? void 0 : _g2.id) || cleanQuestNode.assignee_id,
18296
18473
  `Status "Done" - Finalizado por ${finisherName}`,
18297
18474
  "status_changed"
18298
18475
  )
@@ -18301,8 +18478,9 @@ function XViewScene({
18301
18478
  const updatedNode = {
18302
18479
  ...cleanQuestNode,
18303
18480
  status: nextStatus,
18304
- color: nextStatus === "Done" ? "#22c55e" : "#a855f7",
18305
- assignee_id: nextAssigneeId,
18481
+ color: QUEST_STATUS_COLORS[nextStatus],
18482
+ assignee_id: nextAssigneeId || null,
18483
+ assignees: updatedAssignees,
18306
18484
  reviewStack,
18307
18485
  timeline: newTimeline
18308
18486
  };
@@ -18541,6 +18719,11 @@ function XViewScene({
18541
18719
  }
18542
18720
  });
18543
18721
  }
18722
+ console.log("[handleRenderAncestry] Start", {
18723
+ ancestryId: ancestryObject.ancestry_id,
18724
+ allowedSectionIds: allowedSectionIds ? Array.from(allowedSectionIds) : null,
18725
+ activeSectionIdForFocus
18726
+ });
18544
18727
  const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
18545
18728
  const currentRenderLimit = stateRef.current.maxAncestryRenderIndex || 0;
18546
18729
  const isFullRenderRequest = !normalizedAllowedIds;
@@ -18838,6 +19021,11 @@ function XViewScene({
18838
19021
  let currentAnchorPosition = currentAnchorMesh.userData.id ? targetPositionsCache.get(String(currentAnchorMesh.userData.id)) || currentAnchorMesh.position : currentAnchorMesh.position;
18839
19022
  for (const section of sections) {
18840
19023
  const deveRenderizar = checkShouldRender(section);
19024
+ console.log("[handleRenderAncestry] Section check:", {
19025
+ id: section.id,
19026
+ numericId: section.section_numeric_id,
19027
+ deveRenderizar
19028
+ });
18841
19029
  if (deveRenderizar) {
18842
19030
  const sectionNodes = section.children || [];
18843
19031
  if (sectionNodes.length > 0) {
@@ -19679,8 +19867,15 @@ function XViewScene({
19679
19867
  }, []);
19680
19868
  const handleSaveAncestry = (0, import_react33.useCallback)(
19681
19869
  async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
19870
+ var _a2, _b2;
19682
19871
  const treeToUse = treeOverride || ancestryMode.tree;
19683
19872
  const { isEditMode, currentAncestryId } = ancestryMode;
19873
+ console.log("[handleSaveAncestry] received:", {
19874
+ name: ancestryName,
19875
+ descLength: ancestryDescription == null ? void 0 : ancestryDescription.length,
19876
+ sectionsCount: ancestrySections == null ? void 0 : ancestrySections.length,
19877
+ treeRoot: (_a2 = treeToUse.node) == null ? void 0 : _a2.id
19878
+ });
19684
19879
  if (!treeToUse || !treeToUse.node) {
19685
19880
  alert(
19686
19881
  "Erro: A estrutura da ancestralidade \xE9 inv\xE1lida (Node raiz ausente)."
@@ -19884,6 +20079,12 @@ function XViewScene({
19884
20079
  currentAncestryId: ancestryObjectToSave.ancestry_id
19885
20080
  }));
19886
20081
  }
20082
+ if (readingMode.isActive && ((_b2 = readingMode.ancestry) == null ? void 0 : _b2.ancestry_id) === ancestryObjectToSave.ancestry_id) {
20083
+ setReadingMode((prev) => ({
20084
+ ...prev,
20085
+ ancestry: ancestryObjectToSave
20086
+ }));
20087
+ }
19887
20088
  handleRenderAncestry({
19888
20089
  ...ancestryObjectToSave,
19889
20090
  _forceUpdate: true
@@ -21173,7 +21374,11 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21173
21374
  if (questsResponse.success) {
21174
21375
  return {
21175
21376
  success: true,
21176
- data: questsResponse.data || { nodes: [], links: [], milestones: [] },
21377
+ data: questsResponse.data || {
21378
+ nodes: [],
21379
+ links: [],
21380
+ milestones: []
21381
+ },
21177
21382
  quest_counter: questsResponse.quest_counter
21178
21383
  };
21179
21384
  }