@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.
- package/dist/components/TaskDetail.d.ts.map +1 -1
- package/dist/components/TasksDrawer.d.ts +1 -0
- package/dist/components/TasksDrawer.d.ts.map +1 -1
- package/dist/components/TasksGeneralSettings.d.ts.map +1 -1
- package/dist/components/TasksPanel.d.ts +7 -0
- package/dist/components/TasksPanel.d.ts.map +1 -0
- package/dist/components/TasksTopbarButton.d.ts.map +1 -1
- package/dist/index.cjs +222 -110
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +225 -113
- package/dist/index.js.map +1 -1
- package/dist/locales/en.d.ts.map +1 -1
- package/dist/locales/pt-BR.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/components/TaskDetail.tsx +71 -46
- package/src/components/TasksDrawer.tsx +5 -67
- package/src/components/TasksGeneralSettings.tsx +14 -2
- package/src/components/TasksPanel.tsx +94 -0
- package/src/components/TasksTopbarButton.tsx +49 -4
- package/src/index.ts +32 -0
- package/src/locales/en.ts +2 -0
- package/src/locales/pt-BR.ts +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskDetail.d.ts","sourceRoot":"","sources":["../../src/components/TaskDetail.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAA;
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TasksDrawer.d.ts","sourceRoot":"","sources":["../../src/components/TasksDrawer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
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;
|
|
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;
|
|
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(
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
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
|
|
734
|
-
|
|
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
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
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: "
|
|
835
|
+
className: "bg-transparent px-4 pt-3 text-sm font-semibold text-foreground outline-none"
|
|
798
836
|
}
|
|
799
|
-
)
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
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.
|
|
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:
|
|
872
|
-
|
|
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.
|
|
875
|
-
t("tasks.detail.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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({
|
|
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,
|