@fayz-ai/plugin-tasks 0.8.0 → 0.8.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"TaskDetail.d.ts","sourceRoot":"","sources":["../../src/components/TaskDetail.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAA;AAsB/D,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,qBAiKxD"}
1
+ {"version":3,"file":"TaskDetail.d.ts","sourceRoot":"","sources":["../../src/components/TaskDetail.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAA;AA4B/D,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,qBAoLxD"}
@@ -1,3 +1,4 @@
1
1
  import React from 'react';
2
+ /** Tasks as a sheet — the fallback where the shell has no right rail. */
2
3
  export declare function TasksDrawer(): React.JSX.Element;
3
4
  //# sourceMappingURL=TasksDrawer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TasksDrawer.d.ts","sourceRoot":"","sources":["../../src/components/TasksDrawer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAgBzB,wBAAgB,WAAW,sBA6E1B"}
1
+ {"version":3,"file":"TasksDrawer.d.ts","sourceRoot":"","sources":["../../src/components/TasksDrawer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,yEAAyE;AACzE,wBAAgB,WAAW,sBAsB1B"}
@@ -1 +1 @@
1
- {"version":3,"file":"TasksGeneralSettings.d.ts","sourceRoot":"","sources":["../../src/components/TasksGeneralSettings.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,wBAAgB,oBAAoB,sBAyBnC"}
1
+ {"version":3,"file":"TasksGeneralSettings.d.ts","sourceRoot":"","sources":["../../src/components/TasksGeneralSettings.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAUzB,wBAAgB,oBAAoB,sBA8BnC"}
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ /** The task list with no box around it — shared by the sheet and the shell's
3
+ * right-rail tab. */
4
+ export declare function TasksPanel(): React.JSX.Element;
5
+ /** One-line summary of what needs attention ("3 atrasadas · 2 para hoje"). */
6
+ export declare function useTasksSummaryLine(): string;
7
+ //# sourceMappingURL=TasksPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TasksPanel.d.ts","sourceRoot":"","sources":["../../src/components/TasksPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAazB;sBACsB;AACtB,wBAAgB,UAAU,sBAiEzB;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,IAAI,MAAM,CAU5C"}
@@ -1 +1 @@
1
- {"version":3,"file":"TasksTopbarButton.d.ts","sourceRoot":"","sources":["../../src/components/TasksTopbarButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAA;AAIxC,OAAO,EAAwB,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAEhF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEjD,UAAU,sBAAsB;IAC9B,MAAM,EAAE;QACN,WAAW,EAAE,mBAAmB,CAAA;QAChC,aAAa,EAAE,iBAAiB,CAAA;QAChC,UAAU,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAA;KACnC,CAAA;CACF;AAED,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,EAAE,sBAAsB,qBASnE"}
1
+ {"version":3,"file":"TasksTopbarButton.d.ts","sourceRoot":"","sources":["../../src/components/TasksTopbarButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAA;AAMxC,OAAO,EAAwB,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAGhF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEjD,UAAU,sBAAsB;IAC9B,MAAM,EAAE;QACN,WAAW,EAAE,mBAAmB,CAAA;QAChC,aAAa,EAAE,iBAAiB,CAAA;QAChC,UAAU,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAA;KACnC,CAAA;CACF;AAED,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,EAAE,sBAAsB,qBA4CnE"}
package/dist/index.cjs CHANGED
@@ -406,6 +406,8 @@ var en = {
406
406
  "tasks.detail.delete": "Delete Task",
407
407
  "tasks.detail.deleteConfirm": "Are you sure you want to delete this task?",
408
408
  "tasks.detail.created": "Created",
409
+ "tasks.detail.chatWithAi": "Chat with AI",
410
+ "tasks.detail.chatWithAi.prompt": "Take over this task and help me resolve it now, using your tools when needed:",
409
411
  "tasks.detail.updated": "Updated",
410
412
  "tasks.detail.addSubtask": "Add subtask...",
411
413
  "tasks.detail.back": "Back to list",
@@ -448,6 +450,8 @@ var ptBR = {
448
450
  "tasks.detail.delete": "Excluir Tarefa",
449
451
  "tasks.detail.deleteConfirm": "Tem certeza que deseja excluir esta tarefa?",
450
452
  "tasks.detail.created": "Criada em",
453
+ "tasks.detail.chatWithAi": "Conversar com IA",
454
+ "tasks.detail.chatWithAi.prompt": "Assuma esta tarefa e me ajude a resolver agora, usando suas ferramentas quando precisar:",
451
455
  "tasks.detail.updated": "Atualizada em",
452
456
  "tasks.detail.addSubtask": "Adicionar subtarefa...",
453
457
  "tasks.detail.back": "Voltar \xE0 lista",
@@ -496,8 +500,12 @@ var tasksRegistries = [
496
500
  ]
497
501
  }
498
502
  ];
503
+ var TASKS_DEFAULTS = {
504
+ defaultPriority: "medium"
505
+ };
499
506
  function TasksGeneralSettings() {
500
507
  const t = core.useTranslation();
508
+ const s = saas.useTenantPluginSettings("tasks", TASKS_DEFAULTS);
501
509
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
502
510
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
503
511
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold mb-1", children: t("tasks.settings.general") }),
@@ -505,12 +513,20 @@ function TasksGeneralSettings() {
505
513
  ] }),
506
514
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
507
515
  /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium", children: t("tasks.settings.defaultPriority") }),
508
- /* @__PURE__ */ jsxRuntime.jsxs("select", { className: "w-full max-w-xs rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-3 py-2 text-sm", children: [
509
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "low", children: t("tasks.priority.low") }),
510
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "medium", selected: true, children: t("tasks.priority.medium") }),
511
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "high", children: t("tasks.priority.high") }),
512
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "urgent", children: t("tasks.priority.urgent") })
513
- ] })
516
+ /* @__PURE__ */ jsxRuntime.jsxs(
517
+ "select",
518
+ {
519
+ className: "w-full max-w-xs rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-3 py-2 text-sm",
520
+ value: s.get("defaultPriority"),
521
+ onChange: (e) => s.set("defaultPriority", e.target.value),
522
+ children: [
523
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "low", children: t("tasks.priority.low") }),
524
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "medium", children: t("tasks.priority.medium") }),
525
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "high", children: t("tasks.priority.high") }),
526
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "urgent", children: t("tasks.priority.urgent") })
527
+ ]
528
+ }
529
+ )
514
530
  ] }) })
515
531
  ] });
516
532
  }
@@ -730,8 +746,10 @@ var STATUS_DOT = {
730
746
  done: "bg-success",
731
747
  cancelled: "bg-muted-foreground/60"
732
748
  };
733
- function formatDate(iso) {
734
- return new Date(iso).toLocaleDateString(void 0, { month: "short", day: "numeric" });
749
+ function formatDateTime(iso) {
750
+ const d = new Date(iso);
751
+ const sameDay = d.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
752
+ return sameDay ? d.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit" }) : d.toLocaleDateString(void 0, { day: "2-digit", month: "2-digit", year: "2-digit" });
735
753
  }
736
754
  function TaskDetail({ taskId }) {
737
755
  const t = core.useTranslation();
@@ -740,6 +758,7 @@ function TaskDetail({ taskId }) {
740
758
  const updateTask = useTasksStore((s) => s.updateTask);
741
759
  const deleteTask = useTasksStore((s) => s.deleteTask);
742
760
  const task = tasks.find((tt) => tt.id === taskId);
761
+ const delegate = saas.useDelegateToAssistant();
743
762
  const [title, setTitle] = React4.useState("");
744
763
  const [description, setDescription] = React4.useState("");
745
764
  const [subtasks, setSubtasks] = React4.useState([]);
@@ -773,17 +792,36 @@ function TaskDetail({ taskId }) {
773
792
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => selectTask(null), className: "mt-2 text-xs text-primary hover:underline", children: t("tasks.detail.back") })
774
793
  ] });
775
794
  }
776
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
777
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
778
- /* @__PURE__ */ jsxRuntime.jsx(
779
- "button",
780
- {
781
- type: "button",
782
- onClick: () => selectTask(null),
783
- className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-muted hover:text-foreground transition-colors",
784
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { className: "h-4 w-4" })
785
- }
786
- ),
795
+ return (
796
+ // Same frame as the Notes editor: header row with back + icon actions,
797
+ // full-bleed px-4 content, sectioned by hairlines, thin timestamp footer.
798
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-full flex-col", children: [
799
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 border-b border-border/40 px-2 py-1.5", children: [
800
+ /* @__PURE__ */ jsxRuntime.jsxs(
801
+ "button",
802
+ {
803
+ type: "button",
804
+ onClick: () => selectTask(null),
805
+ className: "inline-flex items-center gap-1 rounded-lg px-1.5 py-1 text-[11.5px] text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
806
+ children: [
807
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { className: "h-3.5 w-3.5" }),
808
+ t("tasks.drawer.title")
809
+ ]
810
+ }
811
+ ),
812
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1" }),
813
+ /* @__PURE__ */ jsxRuntime.jsx(
814
+ "button",
815
+ {
816
+ type: "button",
817
+ onClick: handleDelete,
818
+ "aria-label": t("tasks.detail.delete"),
819
+ title: t("tasks.detail.delete"),
820
+ className: "inline-flex h-7 w-7 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-muted hover:text-destructive",
821
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" })
822
+ }
823
+ )
824
+ ] }),
787
825
  /* @__PURE__ */ jsxRuntime.jsx(
788
826
  "input",
789
827
  {
@@ -794,101 +832,112 @@ function TaskDetail({ taskId }) {
794
832
  onKeyDown: (e) => {
795
833
  if (e.key === "Enter") e.currentTarget.blur();
796
834
  },
797
- className: "flex-1 bg-transparent text-sm font-semibold outline-none"
835
+ className: "bg-transparent px-4 pt-3 text-sm font-semibold text-foreground outline-none"
798
836
  }
799
- )
800
- ] }),
801
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
802
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
803
- /* @__PURE__ */ jsxRuntime.jsx(
804
- "select",
805
- {
806
- value: task.status,
807
- onChange: (e) => updateTask(task.id, { status: e.target.value }),
808
- className: "appearance-none rounded-full border bg-background pl-5 pr-6 py-1 text-xs font-medium cursor-pointer hover:border-primary/40 transition-colors",
809
- children: TASK_STATUSES.map((s) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: s, children: t(`tasks.status.${s}`) }, s))
810
- }
811
- ),
812
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `absolute left-2 top-1/2 -translate-y-1/2 h-2 w-2 rounded-full ${STATUS_DOT[task.status]}` }),
813
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "absolute right-1.5 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
814
- ] }),
815
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
816
- /* @__PURE__ */ jsxRuntime.jsx(
817
- "select",
818
- {
819
- value: task.priority,
820
- onChange: (e) => updateTask(task.id, { priority: e.target.value }),
821
- className: "appearance-none rounded-full border bg-background pl-2 pr-6 py-1 text-xs font-medium cursor-pointer hover:border-primary/40 transition-colors",
822
- children: TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p, children: t(`tasks.priority.${p}`) }, p))
823
- }
824
- ),
825
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "absolute right-1.5 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
826
- ] }),
827
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
828
- /* @__PURE__ */ jsxRuntime.jsx(
829
- "input",
830
- {
831
- type: "date",
832
- value: task.dueDate ?? "",
833
- onChange: (e) => updateTask(task.id, { dueDate: e.target.value || null }),
834
- className: "appearance-none rounded-full border bg-background pl-6 pr-2 py-1 text-xs font-medium cursor-pointer hover:border-primary/40 transition-colors w-[120px]"
835
- }
836
- ),
837
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "absolute left-2 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
838
- ] }),
839
- task.labels.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(TaskLabelBadges, { labelIds: task.labels, max: 3 })
840
- ] }),
841
- /* @__PURE__ */ jsxRuntime.jsx(
842
- "textarea",
843
- {
844
- value: description,
845
- onChange: (e) => setDescription(e.target.value),
846
- onBlur: handleDescriptionBlur,
847
- placeholder: t("tasks.detail.descriptionPlaceholder"),
848
- rows: 3,
849
- className: "w-full rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-3 py-2 text-xs outline-none resize-none placeholder:text-muted-foreground/50 leading-relaxed"
850
- }
851
- ),
852
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
853
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1", children: t("tasks.detail.subtasks") }),
854
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md border overflow-hidden", children: [
855
- /* @__PURE__ */ jsxRuntime.jsx(TaskQuickAdd, { parentId: task.id }),
856
- subtasks.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y", children: subtasks.map((st) => /* @__PURE__ */ jsxRuntime.jsx(TaskCard, { task: st }, st.id)) })
857
- ] })
858
- ] }),
859
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between pt-2 border-t", children: [
860
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
861
- formatDate(task.createdAt),
862
- " \xB7 ",
863
- t("tasks.detail.updated"),
864
- " ",
865
- formatDate(task.updatedAt)
837
+ ),
838
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-1.5 px-4 pt-2", children: [
839
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
840
+ /* @__PURE__ */ jsxRuntime.jsx(
841
+ "select",
842
+ {
843
+ value: task.status,
844
+ onChange: (e) => updateTask(task.id, { status: e.target.value }),
845
+ className: "appearance-none rounded-full border bg-background pl-5 pr-6 py-1 text-xs font-medium cursor-pointer hover:border-primary/40 transition-colors",
846
+ children: TASK_STATUSES.map((s) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: s, children: t(`tasks.status.${s}`) }, s))
847
+ }
848
+ ),
849
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `absolute left-2 top-1/2 -translate-y-1/2 h-2 w-2 rounded-full ${STATUS_DOT[task.status]}` }),
850
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "absolute right-1.5 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
851
+ ] }),
852
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
853
+ /* @__PURE__ */ jsxRuntime.jsx(
854
+ "select",
855
+ {
856
+ value: task.priority,
857
+ onChange: (e) => updateTask(task.id, { priority: e.target.value }),
858
+ className: "appearance-none rounded-full border bg-background pl-2 pr-6 py-1 text-xs font-medium cursor-pointer hover:border-primary/40 transition-colors",
859
+ children: TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p, children: t(`tasks.priority.${p}`) }, p))
860
+ }
861
+ ),
862
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "absolute right-1.5 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
863
+ ] }),
864
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
865
+ /* @__PURE__ */ jsxRuntime.jsx(
866
+ "input",
867
+ {
868
+ type: "date",
869
+ value: task.dueDate ?? "",
870
+ onChange: (e) => updateTask(task.id, { dueDate: e.target.value || null }),
871
+ className: "appearance-none rounded-full border bg-background pl-6 pr-2 py-1 text-xs font-medium cursor-pointer hover:border-primary/40 transition-colors w-[120px]"
872
+ }
873
+ ),
874
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { className: "absolute left-2 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
875
+ ] }),
876
+ task.labels.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(TaskLabelBadges, { labelIds: task.labels, max: 3 })
866
877
  ] }),
867
- /* @__PURE__ */ jsxRuntime.jsxs(
878
+ /* @__PURE__ */ jsxRuntime.jsx(
879
+ "textarea",
880
+ {
881
+ value: description,
882
+ onChange: (e) => setDescription(e.target.value),
883
+ onBlur: handleDescriptionBlur,
884
+ placeholder: t("tasks.detail.descriptionPlaceholder"),
885
+ className: "min-h-[72px] flex-1 resize-none bg-transparent px-4 py-3 text-sm leading-relaxed text-foreground outline-none placeholder:text-muted-foreground/60"
886
+ }
887
+ ),
888
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 pb-2", children: /* @__PURE__ */ jsxRuntime.jsxs(
868
889
  "button",
869
890
  {
870
891
  type: "button",
871
- onClick: handleDelete,
872
- className: "inline-flex items-center gap-1 text-[11px] text-muted-foreground hover:text-destructive transition-colors",
892
+ onClick: () => delegate(
893
+ `${t("tasks.detail.chatWithAi.prompt")}
894
+
895
+ "${task.title}"${task.description ? `
896
+ ${task.description}` : ""}${task.dueDate ? `
897
+ (${t("tasks.detail.dueDate")}: ${task.dueDate})` : ""}`
898
+ ),
899
+ className: "group flex w-full items-center justify-center gap-2 rounded-xl bg-gradient-to-r from-primary via-primary/80 to-primary bg-[length:200%_100%] bg-left px-3 py-2 text-[13px] font-semibold text-primary-foreground shadow-sm transition-all duration-500 hover:bg-right hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
873
900
  children: [
874
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3 w-3" }),
875
- t("tasks.detail.delete")
901
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-4 w-4 transition-transform duration-300 group-hover:rotate-12" }),
902
+ t("tasks.detail.chatWithAi")
876
903
  ]
877
904
  }
878
- )
905
+ ) }),
906
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-border/40 px-4 py-2.5", children: [
907
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "pb-1.5 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground/60", children: [
908
+ t("tasks.detail.subtasks"),
909
+ subtasks.length > 0 ? ` \xB7 ${subtasks.length}` : ""
910
+ ] }),
911
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "-mx-3", children: /* @__PURE__ */ jsxRuntime.jsx(TaskQuickAdd, { parentId: task.id }) }),
912
+ subtasks.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-border/40", children: subtasks.map((st) => /* @__PURE__ */ jsxRuntime.jsx(TaskCard, { task: st }, st.id)) })
913
+ ] }),
914
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "border-t border-border/40 px-4 py-1.5 text-[10px] text-muted-foreground/60", children: [
915
+ t("tasks.detail.created"),
916
+ " ",
917
+ formatDateTime(task.createdAt),
918
+ " \xB7 ",
919
+ t("tasks.detail.updated"),
920
+ " ",
921
+ formatDateTime(task.updatedAt)
922
+ ] })
879
923
  ] })
880
- ] });
924
+ );
881
925
  }
882
926
  var STATUS_ORDER = ["todo", "in_progress", "done", "cancelled"];
883
- function TasksDrawer() {
927
+ function TasksPanel() {
884
928
  const t = core.useTranslation();
885
- const drawerOpen = useTasksStore((s) => s.drawerOpen);
886
- const closeDrawer = useTasksStore((s) => s.closeDrawer);
887
929
  const selectedTaskId = useTasksStore((s) => s.selectedTaskId);
888
930
  const tasks = useTasksStore((s) => s.tasks);
889
931
  const tasksLoading = useTasksStore((s) => s.tasksLoading);
890
- const summary = useTasksStore((s) => s.summary);
891
932
  const activeFilter = useTasksStore((s) => s.activeFilter);
933
+ const fetchTasks = useTasksStore((s) => s.fetchTasks);
934
+ const fetchLabels = useTasksStore((s) => s.fetchLabels);
935
+ const fetchSummary = useTasksStore((s) => s.fetchSummary);
936
+ React4__default.default.useEffect(() => {
937
+ void fetchTasks();
938
+ void fetchLabels();
939
+ void fetchSummary();
940
+ }, [fetchTasks, fetchLabels, fetchSummary]);
892
941
  const grouped = React4__default.default.useMemo(() => {
893
942
  const map = /* @__PURE__ */ new Map();
894
943
  for (const s of STATUS_ORDER) map.set(s, []);
@@ -898,13 +947,32 @@ function TasksDrawer() {
898
947
  }
899
948
  return map;
900
949
  }, [tasks]);
901
- const summaryLine = React4__default.default.useMemo(() => {
950
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
951
+ !selectedTaskId && /* @__PURE__ */ jsxRuntime.jsx(TasksFilterBar, {}),
952
+ !selectedTaskId && /* @__PURE__ */ jsxRuntime.jsx(TaskQuickAdd, {}),
953
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1 overflow-y-auto", children: selectedTaskId ? /* @__PURE__ */ jsxRuntime.jsx(TaskDetail, { taskId: selectedTaskId }) : tasksLoading && tasks.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-primary border-t-transparent" }) }) : tasks.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-muted-foreground", children: [
954
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ClipboardList, { className: "mb-3 h-10 w-10 opacity-40" }),
955
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: t("tasks.empty") }),
956
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs", children: t("tasks.empty.description") })
957
+ ] }) : activeFilter !== "all" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-1", children: tasks.map((task) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2", children: /* @__PURE__ */ jsxRuntime.jsx(TaskCard, { task }) }, task.id)) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2 py-2", children: STATUS_ORDER.filter((s) => s !== "cancelled" || (grouped.get(s)?.length ?? 0) > 0).map((status) => /* @__PURE__ */ jsxRuntime.jsx(TaskStatusGroup, { status, tasks: grouped.get(status) ?? [] }, status)) }) })
958
+ ] });
959
+ }
960
+ function useTasksSummaryLine() {
961
+ const t = core.useTranslation();
962
+ const summary = useTasksStore((s) => s.summary);
963
+ return React4__default.default.useMemo(() => {
902
964
  if (!summary) return "";
903
965
  const parts = [];
904
966
  if (summary.overdue > 0) parts.push(`${summary.overdue} ${t("tasks.summary.overdue")}`);
905
967
  if (summary.dueToday > 0) parts.push(`${summary.dueToday} ${t("tasks.summary.dueToday")}`);
906
968
  return parts.join(" \xB7 ");
907
969
  }, [summary, t]);
970
+ }
971
+ function TasksDrawer() {
972
+ const t = core.useTranslation();
973
+ const drawerOpen = useTasksStore((s) => s.drawerOpen);
974
+ const closeDrawer = useTasksStore((s) => s.closeDrawer);
975
+ const summaryLine = useTasksSummaryLine();
908
976
  return /* @__PURE__ */ jsxRuntime.jsx(ui.Sheet, { open: drawerOpen, onOpenChange: (v) => {
909
977
  if (!v) closeDrawer();
910
978
  }, children: /* @__PURE__ */ jsxRuntime.jsxs(ui.SheetContent, { width: "max-w-lg", overlay: "dim", children: [
@@ -912,26 +980,46 @@ function TasksDrawer() {
912
980
  /* @__PURE__ */ jsxRuntime.jsx(ui.SheetTitle, { children: t("tasks.drawer.title") }),
913
981
  /* @__PURE__ */ jsxRuntime.jsx(ui.SheetDescription, { children: summaryLine || t("tasks.drawer.subtitle") })
914
982
  ] }),
915
- !selectedTaskId && /* @__PURE__ */ jsxRuntime.jsx(TasksFilterBar, {}),
916
- !selectedTaskId && /* @__PURE__ */ jsxRuntime.jsx(TaskQuickAdd, {}),
917
- /* @__PURE__ */ jsxRuntime.jsx(ui.SheetBody, { className: "px-0 py-0", children: selectedTaskId ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(TaskDetail, { taskId: selectedTaskId }) }) : tasksLoading && tasks.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-primary border-t-transparent" }) }) : tasks.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-muted-foreground", children: [
918
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ClipboardList, { className: "h-10 w-10 mb-3 opacity-40" }),
919
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: t("tasks.empty") }),
920
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs mt-1", children: t("tasks.empty.description") })
921
- ] }) : activeFilter !== "all" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-1", children: tasks.map((task) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2", children: /* @__PURE__ */ jsxRuntime.jsx(TaskCard, { task }) }, task.id)) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2 space-y-2", children: STATUS_ORDER.filter((s) => s !== "cancelled" || (grouped.get(s)?.length ?? 0) > 0).map((status) => /* @__PURE__ */ jsxRuntime.jsx(TaskStatusGroup, { status, tasks: grouped.get(status) ?? [] }, status)) }) })
983
+ /* @__PURE__ */ jsxRuntime.jsx(ui.SheetBody, { className: "flex flex-col px-0 py-0", children: /* @__PURE__ */ jsxRuntime.jsx(TasksPanel, {}) })
922
984
  ] }) });
923
985
  }
924
986
  function TasksTopbarButton({ config }) {
925
987
  const { tasksConfig, tasksProvider, tasksStore } = config;
988
+ const t = core.useTranslation();
989
+ const railMounted = saas.useRightRailStore((s) => s.mounted);
990
+ const summary = zustand.useStore(tasksStore, (s) => s.summary);
991
+ const openCount = summary ? summary.todo + summary.inProgress : 0;
992
+ const Panel = React4__default.default.useMemo(() => {
993
+ const RailPanel = () => /* @__PURE__ */ jsxRuntime.jsx(TasksContextProvider, { config: tasksConfig, provider: tasksProvider, store: tasksStore, children: /* @__PURE__ */ jsxRuntime.jsx(TasksPanel, {}) });
994
+ RailPanel.displayName = "TasksRailPanel";
995
+ return RailPanel;
996
+ }, [tasksConfig, tasksProvider, tasksStore]);
997
+ saas.useRightRailPanel(
998
+ React4__default.default.useMemo(
999
+ () => railMounted ? {
1000
+ id: "tasks",
1001
+ label: t("tasks.drawer.title") || "Tasks",
1002
+ icon: lucideReact.CheckSquare,
1003
+ order: 20,
1004
+ badge: { count: openCount, tone: "destructive" },
1005
+ Component: Panel
1006
+ } : null,
1007
+ [railMounted, t, Panel, openCount]
1008
+ )
1009
+ );
926
1010
  return /* @__PURE__ */ jsxRuntime.jsxs(TasksContextProvider, { config: tasksConfig, provider: tasksProvider, store: tasksStore, children: [
927
- /* @__PURE__ */ jsxRuntime.jsx(TasksTopbarButtonInner, { store: tasksStore }),
928
- /* @__PURE__ */ jsxRuntime.jsx(TasksDrawer, {})
1011
+ /* @__PURE__ */ jsxRuntime.jsx(TasksTopbarButtonInner, { store: tasksStore, railMounted }),
1012
+ !railMounted && /* @__PURE__ */ jsxRuntime.jsx(TasksDrawer, {})
929
1013
  ] });
930
1014
  }
931
- function TasksTopbarButtonInner({ store }) {
1015
+ function TasksTopbarButtonInner({
1016
+ store,
1017
+ railMounted
1018
+ }) {
932
1019
  const toggleDrawer = zustand.useStore(store, (s) => s.toggleDrawer);
933
1020
  const fetchSummary = zustand.useStore(store, (s) => s.fetchSummary);
934
1021
  const summary = zustand.useStore(store, (s) => s.summary);
1022
+ const togglePanel = saas.useRightRailStore((s) => s.togglePanel);
935
1023
  React4.useEffect(() => {
936
1024
  fetchSummary();
937
1025
  }, [fetchSummary]);
@@ -942,7 +1030,7 @@ function TasksTopbarButtonInner({ store }) {
942
1030
  variant: "ghost",
943
1031
  size: "icon",
944
1032
  className: ui.cn("relative text-sidebar-foreground/70 hover:bg-sidebar/30 hover:text-sidebar-foreground"),
945
- onClick: toggleDrawer,
1033
+ onClick: () => railMounted ? togglePanel("tasks") : toggleDrawer(),
946
1034
  "aria-label": "Tasks",
947
1035
  children: [
948
1036
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckSquare, { className: "h-5 w-5" }),
@@ -1061,6 +1149,30 @@ function createTasksPlugin(options) {
1061
1149
  () => createMockTasksProvider()
1062
1150
  );
1063
1151
  const store = createTasksStore(provider);
1152
+ saas.registerNotesTasksAdapter({
1153
+ async createTodo({ title, noteId, noteTitle }) {
1154
+ const task = await provider.createTask({
1155
+ title,
1156
+ description: noteTitle ? `Nota: ${noteTitle}` : void 0,
1157
+ labels: [`${saas.NOTE_LABEL_PREFIX}${noteId}`]
1158
+ });
1159
+ void store.getState().fetchSummary();
1160
+ return { id: task.id, title: task.title, done: task.status === "done" };
1161
+ },
1162
+ async listTodos(noteId) {
1163
+ const tasks = await provider.getTasks({});
1164
+ const label = `${saas.NOTE_LABEL_PREFIX}${noteId}`;
1165
+ return tasks.filter((t) => t.labels.includes(label)).sort((a, b) => (a.status === "done" ? 1 : 0) - (b.status === "done" ? 1 : 0)).map((t) => ({ id: t.id, title: t.title, done: t.status === "done" }));
1166
+ },
1167
+ async toggleTodo(id, done) {
1168
+ await provider.updateTask(id, { status: done ? "done" : "todo" });
1169
+ void store.getState().fetchSummary();
1170
+ },
1171
+ async removeTodo(id) {
1172
+ await provider.deleteTask(id);
1173
+ void store.getState().fetchSummary();
1174
+ }
1175
+ });
1064
1176
  return {
1065
1177
  id: "tasks",
1066
1178
  name: config.labels.drawerTitle,