@fayz-ai/plugin-tasks 0.8.0 → 0.9.0-next.0
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.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 +13 -11
- 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
- package/dist/index.cjs +0 -1151
- package/dist/index.cjs.map +0 -1
|
@@ -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.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC5E,OAAO,EAAkD,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACvG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC5E,OAAO,EAAkD,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACvG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAgB3C,MAAM,WAAW,kBAAkB;IACjC,sBAAsB;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAA;IACnC,mBAAmB;IACnB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,kBAAkB;IAClB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,iBAAiB,CAAA;IAChC,yDAAyD;IACzD,eAAe,CAAC,EAAE,YAAY,CAAA;CAC/B;AA2BD,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,cAAc,CAoI9E;AAMD,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AACrD,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAC5E,YAAY,EACV,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EACvD,eAAe,EAAE,eAAe,EAAE,SAAS,GAC5C,MAAM,SAAS,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React4, { useEffect, useState, useCallback } from 'react';
|
|
2
|
-
import { createPluginContext, dedup } from '@fayz-ai/saas';
|
|
2
|
+
import { createPluginContext, registerNotesTasksAdapter, NOTE_LABEL_PREFIX, dedup, useRightRailStore, useRightRailPanel, useTenantPluginSettings, useDelegateToAssistant } from '@fayz-ai/saas';
|
|
3
3
|
import { registerTranslations, createSafeDataProvider, useTranslation, getActiveTenantId, getSupabaseClientOptional } from '@fayz-ai/core';
|
|
4
4
|
import { createStore } from 'zustand/vanilla';
|
|
5
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
-
import { CheckSquare, ClipboardList, Plus, ArrowLeft, ChevronDown, Calendar,
|
|
5
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
6
|
+
import { CheckSquare, ClipboardList, Plus, ArrowLeft, Trash2, ChevronDown, Calendar, Sparkles, ListChecks, ChevronRight, AlertTriangle, ArrowUp, Minus, ArrowDown } from 'lucide-react';
|
|
7
7
|
import { Button, cn, Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetBody, Checkbox } from '@fayz-ai/ui';
|
|
8
8
|
import { useStore } from 'zustand';
|
|
9
9
|
|
|
@@ -400,6 +400,8 @@ var en = {
|
|
|
400
400
|
"tasks.detail.delete": "Delete Task",
|
|
401
401
|
"tasks.detail.deleteConfirm": "Are you sure you want to delete this task?",
|
|
402
402
|
"tasks.detail.created": "Created",
|
|
403
|
+
"tasks.detail.chatWithAi": "Chat with AI",
|
|
404
|
+
"tasks.detail.chatWithAi.prompt": "Take over this task and help me resolve it now, using your tools when needed:",
|
|
403
405
|
"tasks.detail.updated": "Updated",
|
|
404
406
|
"tasks.detail.addSubtask": "Add subtask...",
|
|
405
407
|
"tasks.detail.back": "Back to list",
|
|
@@ -442,6 +444,8 @@ var ptBR = {
|
|
|
442
444
|
"tasks.detail.delete": "Excluir Tarefa",
|
|
443
445
|
"tasks.detail.deleteConfirm": "Tem certeza que deseja excluir esta tarefa?",
|
|
444
446
|
"tasks.detail.created": "Criada em",
|
|
447
|
+
"tasks.detail.chatWithAi": "Conversar com IA",
|
|
448
|
+
"tasks.detail.chatWithAi.prompt": "Assuma esta tarefa e me ajude a resolver agora, usando suas ferramentas quando precisar:",
|
|
445
449
|
"tasks.detail.updated": "Atualizada em",
|
|
446
450
|
"tasks.detail.addSubtask": "Adicionar subtarefa...",
|
|
447
451
|
"tasks.detail.back": "Voltar \xE0 lista",
|
|
@@ -490,8 +494,12 @@ var tasksRegistries = [
|
|
|
490
494
|
]
|
|
491
495
|
}
|
|
492
496
|
];
|
|
497
|
+
var TASKS_DEFAULTS = {
|
|
498
|
+
defaultPriority: "medium"
|
|
499
|
+
};
|
|
493
500
|
function TasksGeneralSettings() {
|
|
494
501
|
const t = useTranslation();
|
|
502
|
+
const s = useTenantPluginSettings("tasks", TASKS_DEFAULTS);
|
|
495
503
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
496
504
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
497
505
|
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold mb-1", children: t("tasks.settings.general") }),
|
|
@@ -499,12 +507,20 @@ function TasksGeneralSettings() {
|
|
|
499
507
|
] }),
|
|
500
508
|
/* @__PURE__ */ jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
501
509
|
/* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: t("tasks.settings.defaultPriority") }),
|
|
502
|
-
/* @__PURE__ */ jsxs(
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
510
|
+
/* @__PURE__ */ jsxs(
|
|
511
|
+
"select",
|
|
512
|
+
{
|
|
513
|
+
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",
|
|
514
|
+
value: s.get("defaultPriority"),
|
|
515
|
+
onChange: (e) => s.set("defaultPriority", e.target.value),
|
|
516
|
+
children: [
|
|
517
|
+
/* @__PURE__ */ jsx("option", { value: "low", children: t("tasks.priority.low") }),
|
|
518
|
+
/* @__PURE__ */ jsx("option", { value: "medium", children: t("tasks.priority.medium") }),
|
|
519
|
+
/* @__PURE__ */ jsx("option", { value: "high", children: t("tasks.priority.high") }),
|
|
520
|
+
/* @__PURE__ */ jsx("option", { value: "urgent", children: t("tasks.priority.urgent") })
|
|
521
|
+
]
|
|
522
|
+
}
|
|
523
|
+
)
|
|
508
524
|
] }) })
|
|
509
525
|
] });
|
|
510
526
|
}
|
|
@@ -724,8 +740,10 @@ var STATUS_DOT = {
|
|
|
724
740
|
done: "bg-success",
|
|
725
741
|
cancelled: "bg-muted-foreground/60"
|
|
726
742
|
};
|
|
727
|
-
function
|
|
728
|
-
|
|
743
|
+
function formatDateTime(iso) {
|
|
744
|
+
const d = new Date(iso);
|
|
745
|
+
const sameDay = d.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
|
|
746
|
+
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" });
|
|
729
747
|
}
|
|
730
748
|
function TaskDetail({ taskId }) {
|
|
731
749
|
const t = useTranslation();
|
|
@@ -734,6 +752,7 @@ function TaskDetail({ taskId }) {
|
|
|
734
752
|
const updateTask = useTasksStore((s) => s.updateTask);
|
|
735
753
|
const deleteTask = useTasksStore((s) => s.deleteTask);
|
|
736
754
|
const task = tasks.find((tt) => tt.id === taskId);
|
|
755
|
+
const delegate = useDelegateToAssistant();
|
|
737
756
|
const [title, setTitle] = useState("");
|
|
738
757
|
const [description, setDescription] = useState("");
|
|
739
758
|
const [subtasks, setSubtasks] = useState([]);
|
|
@@ -767,17 +786,36 @@ function TaskDetail({ taskId }) {
|
|
|
767
786
|
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => selectTask(null), className: "mt-2 text-xs text-primary hover:underline", children: t("tasks.detail.back") })
|
|
768
787
|
] });
|
|
769
788
|
}
|
|
770
|
-
return
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
789
|
+
return (
|
|
790
|
+
// Same frame as the Notes editor: header row with back + icon actions,
|
|
791
|
+
// full-bleed px-4 content, sectioned by hairlines, thin timestamp footer.
|
|
792
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-h-full flex-col", children: [
|
|
793
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 border-b border-border/40 px-2 py-1.5", children: [
|
|
794
|
+
/* @__PURE__ */ jsxs(
|
|
795
|
+
"button",
|
|
796
|
+
{
|
|
797
|
+
type: "button",
|
|
798
|
+
onClick: () => selectTask(null),
|
|
799
|
+
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",
|
|
800
|
+
children: [
|
|
801
|
+
/* @__PURE__ */ jsx(ArrowLeft, { className: "h-3.5 w-3.5" }),
|
|
802
|
+
t("tasks.drawer.title")
|
|
803
|
+
]
|
|
804
|
+
}
|
|
805
|
+
),
|
|
806
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1" }),
|
|
807
|
+
/* @__PURE__ */ jsx(
|
|
808
|
+
"button",
|
|
809
|
+
{
|
|
810
|
+
type: "button",
|
|
811
|
+
onClick: handleDelete,
|
|
812
|
+
"aria-label": t("tasks.detail.delete"),
|
|
813
|
+
title: t("tasks.detail.delete"),
|
|
814
|
+
className: "inline-flex h-7 w-7 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-muted hover:text-destructive",
|
|
815
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" })
|
|
816
|
+
}
|
|
817
|
+
)
|
|
818
|
+
] }),
|
|
781
819
|
/* @__PURE__ */ jsx(
|
|
782
820
|
"input",
|
|
783
821
|
{
|
|
@@ -788,101 +826,112 @@ function TaskDetail({ taskId }) {
|
|
|
788
826
|
onKeyDown: (e) => {
|
|
789
827
|
if (e.key === "Enter") e.currentTarget.blur();
|
|
790
828
|
},
|
|
791
|
-
className: "
|
|
829
|
+
className: "bg-transparent px-4 pt-3 text-sm font-semibold text-foreground outline-none"
|
|
792
830
|
}
|
|
793
|
-
)
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
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
|
-
task.labels.length > 0 && /* @__PURE__ */ jsx(TaskLabelBadges, { labelIds: task.labels, max: 3 })
|
|
834
|
-
] }),
|
|
835
|
-
/* @__PURE__ */ jsx(
|
|
836
|
-
"textarea",
|
|
837
|
-
{
|
|
838
|
-
value: description,
|
|
839
|
-
onChange: (e) => setDescription(e.target.value),
|
|
840
|
-
onBlur: handleDescriptionBlur,
|
|
841
|
-
placeholder: t("tasks.detail.descriptionPlaceholder"),
|
|
842
|
-
rows: 3,
|
|
843
|
-
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"
|
|
844
|
-
}
|
|
845
|
-
),
|
|
846
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
847
|
-
/* @__PURE__ */ jsx("p", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1", children: t("tasks.detail.subtasks") }),
|
|
848
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-md border overflow-hidden", children: [
|
|
849
|
-
/* @__PURE__ */ jsx(TaskQuickAdd, { parentId: task.id }),
|
|
850
|
-
subtasks.length > 0 && /* @__PURE__ */ jsx("div", { className: "divide-y", children: subtasks.map((st) => /* @__PURE__ */ jsx(TaskCard, { task: st }, st.id)) })
|
|
851
|
-
] })
|
|
852
|
-
] }),
|
|
853
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pt-2 border-t", children: [
|
|
854
|
-
/* @__PURE__ */ jsxs("span", { className: "text-[10px] text-muted-foreground", children: [
|
|
855
|
-
formatDate(task.createdAt),
|
|
856
|
-
" \xB7 ",
|
|
857
|
-
t("tasks.detail.updated"),
|
|
858
|
-
" ",
|
|
859
|
-
formatDate(task.updatedAt)
|
|
831
|
+
),
|
|
832
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5 px-4 pt-2", children: [
|
|
833
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
834
|
+
/* @__PURE__ */ jsx(
|
|
835
|
+
"select",
|
|
836
|
+
{
|
|
837
|
+
value: task.status,
|
|
838
|
+
onChange: (e) => updateTask(task.id, { status: e.target.value }),
|
|
839
|
+
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",
|
|
840
|
+
children: TASK_STATUSES.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: t(`tasks.status.${s}`) }, s))
|
|
841
|
+
}
|
|
842
|
+
),
|
|
843
|
+
/* @__PURE__ */ jsx("span", { className: `absolute left-2 top-1/2 -translate-y-1/2 h-2 w-2 rounded-full ${STATUS_DOT[task.status]}` }),
|
|
844
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "absolute right-1.5 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
|
|
845
|
+
] }),
|
|
846
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
847
|
+
/* @__PURE__ */ jsx(
|
|
848
|
+
"select",
|
|
849
|
+
{
|
|
850
|
+
value: task.priority,
|
|
851
|
+
onChange: (e) => updateTask(task.id, { priority: e.target.value }),
|
|
852
|
+
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",
|
|
853
|
+
children: TASK_PRIORITIES.map((p) => /* @__PURE__ */ jsx("option", { value: p, children: t(`tasks.priority.${p}`) }, p))
|
|
854
|
+
}
|
|
855
|
+
),
|
|
856
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "absolute right-1.5 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
|
|
857
|
+
] }),
|
|
858
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
859
|
+
/* @__PURE__ */ jsx(
|
|
860
|
+
"input",
|
|
861
|
+
{
|
|
862
|
+
type: "date",
|
|
863
|
+
value: task.dueDate ?? "",
|
|
864
|
+
onChange: (e) => updateTask(task.id, { dueDate: e.target.value || null }),
|
|
865
|
+
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]"
|
|
866
|
+
}
|
|
867
|
+
),
|
|
868
|
+
/* @__PURE__ */ jsx(Calendar, { className: "absolute left-2 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground pointer-events-none" })
|
|
869
|
+
] }),
|
|
870
|
+
task.labels.length > 0 && /* @__PURE__ */ jsx(TaskLabelBadges, { labelIds: task.labels, max: 3 })
|
|
860
871
|
] }),
|
|
861
|
-
/* @__PURE__ */
|
|
872
|
+
/* @__PURE__ */ jsx(
|
|
873
|
+
"textarea",
|
|
874
|
+
{
|
|
875
|
+
value: description,
|
|
876
|
+
onChange: (e) => setDescription(e.target.value),
|
|
877
|
+
onBlur: handleDescriptionBlur,
|
|
878
|
+
placeholder: t("tasks.detail.descriptionPlaceholder"),
|
|
879
|
+
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"
|
|
880
|
+
}
|
|
881
|
+
),
|
|
882
|
+
/* @__PURE__ */ jsx("div", { className: "px-4 pb-2", children: /* @__PURE__ */ jsxs(
|
|
862
883
|
"button",
|
|
863
884
|
{
|
|
864
885
|
type: "button",
|
|
865
|
-
onClick:
|
|
866
|
-
|
|
886
|
+
onClick: () => delegate(
|
|
887
|
+
`${t("tasks.detail.chatWithAi.prompt")}
|
|
888
|
+
|
|
889
|
+
"${task.title}"${task.description ? `
|
|
890
|
+
${task.description}` : ""}${task.dueDate ? `
|
|
891
|
+
(${t("tasks.detail.dueDate")}: ${task.dueDate})` : ""}`
|
|
892
|
+
),
|
|
893
|
+
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",
|
|
867
894
|
children: [
|
|
868
|
-
/* @__PURE__ */ jsx(
|
|
869
|
-
t("tasks.detail.
|
|
895
|
+
/* @__PURE__ */ jsx(Sparkles, { className: "h-4 w-4 transition-transform duration-300 group-hover:rotate-12" }),
|
|
896
|
+
t("tasks.detail.chatWithAi")
|
|
870
897
|
]
|
|
871
898
|
}
|
|
872
|
-
)
|
|
899
|
+
) }),
|
|
900
|
+
/* @__PURE__ */ jsxs("div", { className: "border-t border-border/40 px-4 py-2.5", children: [
|
|
901
|
+
/* @__PURE__ */ jsxs("p", { className: "pb-1.5 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground/60", children: [
|
|
902
|
+
t("tasks.detail.subtasks"),
|
|
903
|
+
subtasks.length > 0 ? ` \xB7 ${subtasks.length}` : ""
|
|
904
|
+
] }),
|
|
905
|
+
/* @__PURE__ */ jsx("div", { className: "-mx-3", children: /* @__PURE__ */ jsx(TaskQuickAdd, { parentId: task.id }) }),
|
|
906
|
+
subtasks.length > 0 && /* @__PURE__ */ jsx("div", { className: "divide-y divide-border/40", children: subtasks.map((st) => /* @__PURE__ */ jsx(TaskCard, { task: st }, st.id)) })
|
|
907
|
+
] }),
|
|
908
|
+
/* @__PURE__ */ jsxs("p", { className: "border-t border-border/40 px-4 py-1.5 text-[10px] text-muted-foreground/60", children: [
|
|
909
|
+
t("tasks.detail.created"),
|
|
910
|
+
" ",
|
|
911
|
+
formatDateTime(task.createdAt),
|
|
912
|
+
" \xB7 ",
|
|
913
|
+
t("tasks.detail.updated"),
|
|
914
|
+
" ",
|
|
915
|
+
formatDateTime(task.updatedAt)
|
|
916
|
+
] })
|
|
873
917
|
] })
|
|
874
|
-
|
|
918
|
+
);
|
|
875
919
|
}
|
|
876
920
|
var STATUS_ORDER = ["todo", "in_progress", "done", "cancelled"];
|
|
877
|
-
function
|
|
921
|
+
function TasksPanel() {
|
|
878
922
|
const t = useTranslation();
|
|
879
|
-
const drawerOpen = useTasksStore((s) => s.drawerOpen);
|
|
880
|
-
const closeDrawer = useTasksStore((s) => s.closeDrawer);
|
|
881
923
|
const selectedTaskId = useTasksStore((s) => s.selectedTaskId);
|
|
882
924
|
const tasks = useTasksStore((s) => s.tasks);
|
|
883
925
|
const tasksLoading = useTasksStore((s) => s.tasksLoading);
|
|
884
|
-
const summary = useTasksStore((s) => s.summary);
|
|
885
926
|
const activeFilter = useTasksStore((s) => s.activeFilter);
|
|
927
|
+
const fetchTasks = useTasksStore((s) => s.fetchTasks);
|
|
928
|
+
const fetchLabels = useTasksStore((s) => s.fetchLabels);
|
|
929
|
+
const fetchSummary = useTasksStore((s) => s.fetchSummary);
|
|
930
|
+
React4.useEffect(() => {
|
|
931
|
+
void fetchTasks();
|
|
932
|
+
void fetchLabels();
|
|
933
|
+
void fetchSummary();
|
|
934
|
+
}, [fetchTasks, fetchLabels, fetchSummary]);
|
|
886
935
|
const grouped = React4.useMemo(() => {
|
|
887
936
|
const map = /* @__PURE__ */ new Map();
|
|
888
937
|
for (const s of STATUS_ORDER) map.set(s, []);
|
|
@@ -892,13 +941,32 @@ function TasksDrawer() {
|
|
|
892
941
|
}
|
|
893
942
|
return map;
|
|
894
943
|
}, [tasks]);
|
|
895
|
-
|
|
944
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
945
|
+
!selectedTaskId && /* @__PURE__ */ jsx(TasksFilterBar, {}),
|
|
946
|
+
!selectedTaskId && /* @__PURE__ */ jsx(TaskQuickAdd, {}),
|
|
947
|
+
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-y-auto", children: selectedTaskId ? /* @__PURE__ */ jsx(TaskDetail, { taskId: selectedTaskId }) : tasksLoading && tasks.length === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsx("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-primary border-t-transparent" }) }) : tasks.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-muted-foreground", children: [
|
|
948
|
+
/* @__PURE__ */ jsx(ClipboardList, { className: "mb-3 h-10 w-10 opacity-40" }),
|
|
949
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: t("tasks.empty") }),
|
|
950
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-xs", children: t("tasks.empty.description") })
|
|
951
|
+
] }) : activeFilter !== "all" ? /* @__PURE__ */ jsx("div", { className: "py-1", children: tasks.map((task) => /* @__PURE__ */ jsx("div", { className: "px-2", children: /* @__PURE__ */ jsx(TaskCard, { task }) }, task.id)) }) : /* @__PURE__ */ jsx("div", { className: "space-y-2 py-2", children: STATUS_ORDER.filter((s) => s !== "cancelled" || (grouped.get(s)?.length ?? 0) > 0).map((status) => /* @__PURE__ */ jsx(TaskStatusGroup, { status, tasks: grouped.get(status) ?? [] }, status)) }) })
|
|
952
|
+
] });
|
|
953
|
+
}
|
|
954
|
+
function useTasksSummaryLine() {
|
|
955
|
+
const t = useTranslation();
|
|
956
|
+
const summary = useTasksStore((s) => s.summary);
|
|
957
|
+
return React4.useMemo(() => {
|
|
896
958
|
if (!summary) return "";
|
|
897
959
|
const parts = [];
|
|
898
960
|
if (summary.overdue > 0) parts.push(`${summary.overdue} ${t("tasks.summary.overdue")}`);
|
|
899
961
|
if (summary.dueToday > 0) parts.push(`${summary.dueToday} ${t("tasks.summary.dueToday")}`);
|
|
900
962
|
return parts.join(" \xB7 ");
|
|
901
963
|
}, [summary, t]);
|
|
964
|
+
}
|
|
965
|
+
function TasksDrawer() {
|
|
966
|
+
const t = useTranslation();
|
|
967
|
+
const drawerOpen = useTasksStore((s) => s.drawerOpen);
|
|
968
|
+
const closeDrawer = useTasksStore((s) => s.closeDrawer);
|
|
969
|
+
const summaryLine = useTasksSummaryLine();
|
|
902
970
|
return /* @__PURE__ */ jsx(Sheet, { open: drawerOpen, onOpenChange: (v) => {
|
|
903
971
|
if (!v) closeDrawer();
|
|
904
972
|
}, children: /* @__PURE__ */ jsxs(SheetContent, { width: "max-w-lg", overlay: "dim", children: [
|
|
@@ -906,26 +974,46 @@ function TasksDrawer() {
|
|
|
906
974
|
/* @__PURE__ */ jsx(SheetTitle, { children: t("tasks.drawer.title") }),
|
|
907
975
|
/* @__PURE__ */ jsx(SheetDescription, { children: summaryLine || t("tasks.drawer.subtitle") })
|
|
908
976
|
] }),
|
|
909
|
-
|
|
910
|
-
!selectedTaskId && /* @__PURE__ */ jsx(TaskQuickAdd, {}),
|
|
911
|
-
/* @__PURE__ */ jsx(SheetBody, { className: "px-0 py-0", children: selectedTaskId ? /* @__PURE__ */ jsx("div", { className: "px-5 py-4", children: /* @__PURE__ */ jsx(TaskDetail, { taskId: selectedTaskId }) }) : tasksLoading && tasks.length === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-16", children: /* @__PURE__ */ jsx("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-primary border-t-transparent" }) }) : tasks.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-muted-foreground", children: [
|
|
912
|
-
/* @__PURE__ */ jsx(ClipboardList, { className: "h-10 w-10 mb-3 opacity-40" }),
|
|
913
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: t("tasks.empty") }),
|
|
914
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs mt-1", children: t("tasks.empty.description") })
|
|
915
|
-
] }) : activeFilter !== "all" ? /* @__PURE__ */ jsx("div", { className: "py-1", children: tasks.map((task) => /* @__PURE__ */ jsx("div", { className: "px-2", children: /* @__PURE__ */ jsx(TaskCard, { task }) }, task.id)) }) : /* @__PURE__ */ jsx("div", { className: "py-2 space-y-2", children: STATUS_ORDER.filter((s) => s !== "cancelled" || (grouped.get(s)?.length ?? 0) > 0).map((status) => /* @__PURE__ */ jsx(TaskStatusGroup, { status, tasks: grouped.get(status) ?? [] }, status)) }) })
|
|
977
|
+
/* @__PURE__ */ jsx(SheetBody, { className: "flex flex-col px-0 py-0", children: /* @__PURE__ */ jsx(TasksPanel, {}) })
|
|
916
978
|
] }) });
|
|
917
979
|
}
|
|
918
980
|
function TasksTopbarButton({ config }) {
|
|
919
981
|
const { tasksConfig, tasksProvider, tasksStore } = config;
|
|
982
|
+
const t = useTranslation();
|
|
983
|
+
const railMounted = useRightRailStore((s) => s.mounted);
|
|
984
|
+
const summary = useStore(tasksStore, (s) => s.summary);
|
|
985
|
+
const openCount = summary ? summary.todo + summary.inProgress : 0;
|
|
986
|
+
const Panel = React4.useMemo(() => {
|
|
987
|
+
const RailPanel = () => /* @__PURE__ */ jsx(TasksContextProvider, { config: tasksConfig, provider: tasksProvider, store: tasksStore, children: /* @__PURE__ */ jsx(TasksPanel, {}) });
|
|
988
|
+
RailPanel.displayName = "TasksRailPanel";
|
|
989
|
+
return RailPanel;
|
|
990
|
+
}, [tasksConfig, tasksProvider, tasksStore]);
|
|
991
|
+
useRightRailPanel(
|
|
992
|
+
React4.useMemo(
|
|
993
|
+
() => railMounted ? {
|
|
994
|
+
id: "tasks",
|
|
995
|
+
label: t("tasks.drawer.title") || "Tasks",
|
|
996
|
+
icon: CheckSquare,
|
|
997
|
+
order: 20,
|
|
998
|
+
badge: { count: openCount, tone: "destructive" },
|
|
999
|
+
Component: Panel
|
|
1000
|
+
} : null,
|
|
1001
|
+
[railMounted, t, Panel, openCount]
|
|
1002
|
+
)
|
|
1003
|
+
);
|
|
920
1004
|
return /* @__PURE__ */ jsxs(TasksContextProvider, { config: tasksConfig, provider: tasksProvider, store: tasksStore, children: [
|
|
921
|
-
/* @__PURE__ */ jsx(TasksTopbarButtonInner, { store: tasksStore }),
|
|
922
|
-
/* @__PURE__ */ jsx(TasksDrawer, {})
|
|
1005
|
+
/* @__PURE__ */ jsx(TasksTopbarButtonInner, { store: tasksStore, railMounted }),
|
|
1006
|
+
!railMounted && /* @__PURE__ */ jsx(TasksDrawer, {})
|
|
923
1007
|
] });
|
|
924
1008
|
}
|
|
925
|
-
function TasksTopbarButtonInner({
|
|
1009
|
+
function TasksTopbarButtonInner({
|
|
1010
|
+
store,
|
|
1011
|
+
railMounted
|
|
1012
|
+
}) {
|
|
926
1013
|
const toggleDrawer = useStore(store, (s) => s.toggleDrawer);
|
|
927
1014
|
const fetchSummary = useStore(store, (s) => s.fetchSummary);
|
|
928
1015
|
const summary = useStore(store, (s) => s.summary);
|
|
1016
|
+
const togglePanel = useRightRailStore((s) => s.togglePanel);
|
|
929
1017
|
useEffect(() => {
|
|
930
1018
|
fetchSummary();
|
|
931
1019
|
}, [fetchSummary]);
|
|
@@ -936,7 +1024,7 @@ function TasksTopbarButtonInner({ store }) {
|
|
|
936
1024
|
variant: "ghost",
|
|
937
1025
|
size: "icon",
|
|
938
1026
|
className: cn("relative text-sidebar-foreground/70 hover:bg-sidebar/30 hover:text-sidebar-foreground"),
|
|
939
|
-
onClick: toggleDrawer,
|
|
1027
|
+
onClick: () => railMounted ? togglePanel("tasks") : toggleDrawer(),
|
|
940
1028
|
"aria-label": "Tasks",
|
|
941
1029
|
children: [
|
|
942
1030
|
/* @__PURE__ */ jsx(CheckSquare, { className: "h-5 w-5" }),
|
|
@@ -1055,6 +1143,30 @@ function createTasksPlugin(options) {
|
|
|
1055
1143
|
() => createMockTasksProvider()
|
|
1056
1144
|
);
|
|
1057
1145
|
const store = createTasksStore(provider);
|
|
1146
|
+
registerNotesTasksAdapter({
|
|
1147
|
+
async createTodo({ title, noteId, noteTitle }) {
|
|
1148
|
+
const task = await provider.createTask({
|
|
1149
|
+
title,
|
|
1150
|
+
description: noteTitle ? `Nota: ${noteTitle}` : void 0,
|
|
1151
|
+
labels: [`${NOTE_LABEL_PREFIX}${noteId}`]
|
|
1152
|
+
});
|
|
1153
|
+
void store.getState().fetchSummary();
|
|
1154
|
+
return { id: task.id, title: task.title, done: task.status === "done" };
|
|
1155
|
+
},
|
|
1156
|
+
async listTodos(noteId) {
|
|
1157
|
+
const tasks = await provider.getTasks({});
|
|
1158
|
+
const label = `${NOTE_LABEL_PREFIX}${noteId}`;
|
|
1159
|
+
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" }));
|
|
1160
|
+
},
|
|
1161
|
+
async toggleTodo(id, done) {
|
|
1162
|
+
await provider.updateTask(id, { status: done ? "done" : "todo" });
|
|
1163
|
+
void store.getState().fetchSummary();
|
|
1164
|
+
},
|
|
1165
|
+
async removeTodo(id) {
|
|
1166
|
+
await provider.deleteTask(id);
|
|
1167
|
+
void store.getState().fetchSummary();
|
|
1168
|
+
}
|
|
1169
|
+
});
|
|
1058
1170
|
return {
|
|
1059
1171
|
id: "tasks",
|
|
1060
1172
|
name: config.labels.drawerTitle,
|