realtimex-crm 0.13.8 → 0.14.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.
Files changed (45) hide show
  1. package/dist/assets/DealList-BrMu9tSP.js +59 -0
  2. package/dist/assets/DealList-BrMu9tSP.js.map +1 -0
  3. package/dist/assets/index-5AmasdLr.css +1 -0
  4. package/dist/assets/index-Ce7mf_H5.js +166 -0
  5. package/dist/assets/{index-BrW7DPxi.js.map → index-Ce7mf_H5.js.map} +1 -1
  6. package/dist/index.html +1 -1
  7. package/dist/stats.html +1 -1
  8. package/package.json +1 -1
  9. package/src/components/atomic-crm/deals/DealCreate.tsx +5 -1
  10. package/src/components/atomic-crm/deals/DealShow.tsx +5 -1
  11. package/src/components/atomic-crm/integrations/WebhooksTab.tsx +10 -0
  12. package/src/components/atomic-crm/layout/Header.tsx +6 -0
  13. package/src/components/atomic-crm/notes/NoteCreate.tsx +3 -2
  14. package/src/components/atomic-crm/notes/NotesIterator.tsx +1 -1
  15. package/src/components/atomic-crm/providers/fakerest/dataGenerator/index.ts +4 -0
  16. package/src/components/atomic-crm/providers/fakerest/dataGenerator/taskActivity.ts +62 -0
  17. package/src/components/atomic-crm/providers/fakerest/dataGenerator/taskNotes.ts +29 -0
  18. package/src/components/atomic-crm/providers/fakerest/dataGenerator/tasks.ts +33 -8
  19. package/src/components/atomic-crm/providers/fakerest/dataGenerator/types.ts +4 -0
  20. package/src/components/atomic-crm/providers/supabase/dataProvider.ts +37 -0
  21. package/src/components/atomic-crm/root/CRM.tsx +12 -1
  22. package/src/components/atomic-crm/root/ConfigurationContext.tsx +10 -0
  23. package/src/components/atomic-crm/root/defaultConfiguration.ts +15 -0
  24. package/src/components/atomic-crm/tasks/MyTasksInput.tsx +30 -0
  25. package/src/components/atomic-crm/tasks/Task.tsx +20 -9
  26. package/src/components/atomic-crm/tasks/TaskActivityTimeline.tsx +91 -0
  27. package/src/components/atomic-crm/tasks/TaskAside.tsx +122 -0
  28. package/src/components/atomic-crm/tasks/TaskCreate.tsx +112 -0
  29. package/src/components/atomic-crm/tasks/TaskEdit.tsx +20 -1
  30. package/src/components/atomic-crm/tasks/TaskList.tsx +52 -0
  31. package/src/components/atomic-crm/tasks/TaskListTable.tsx +60 -0
  32. package/src/components/atomic-crm/tasks/TaskPriorityBadge.tsx +20 -0
  33. package/src/components/atomic-crm/tasks/TaskShow.tsx +71 -0
  34. package/src/components/atomic-crm/tasks/TaskStatusBadge.tsx +21 -0
  35. package/src/components/atomic-crm/tasks/index.ts +9 -0
  36. package/src/components/atomic-crm/types.ts +50 -0
  37. package/src/components/ui/visually-hidden.tsx +10 -0
  38. package/supabase/migrations/20251225120000_enhance_tasks_schema.sql +111 -0
  39. package/supabase/migrations/20251225120001_enhance_tasks_logic.sql +109 -0
  40. package/supabase/migrations/20251225120002_enhance_tasks_webhooks.sql +72 -0
  41. package/supabase/migrations/20251225150000_add_taskNotes_attachments.sql +6 -0
  42. package/dist/assets/DealList-CyjZCmZS.js +0 -59
  43. package/dist/assets/DealList-CyjZCmZS.js.map +0 -1
  44. package/dist/assets/index-BrW7DPxi.js +0 -166
  45. package/dist/assets/index-u4GyWWrL.css +0 -1
@@ -0,0 +1,122 @@
1
+ import { Calendar, Building2, UserCircle, UserCheck, Pencil } from "lucide-react";
2
+ import { useRecordContext } from "ra-core";
3
+ import { useState, type ReactNode } from "react";
4
+ import { Button } from "@/components/ui/button";
5
+ import { DeleteButton } from "@/components/admin/delete-button";
6
+ import { ReferenceField } from "@/components/admin/reference-field";
7
+ import { TextField } from "@/components/admin/text-field";
8
+ import { DateField } from "@/components/admin/date-field";
9
+
10
+ import { AsideSection } from "../misc/AsideSection";
11
+ import type { Task } from "../types";
12
+ import { TaskEdit } from "./TaskEdit";
13
+
14
+ export const TaskAside = () => {
15
+ const record = useRecordContext<Task>();
16
+ const [editOpen, setEditOpen] = useState(false);
17
+
18
+ if (!record) return null;
19
+ return (
20
+ <div className="hidden sm:block w-64 min-w-64 text-sm">
21
+ <div className="mb-4 -ml-1">
22
+ <Button
23
+ variant="outline"
24
+ size="sm"
25
+ onClick={() => setEditOpen(true)}
26
+ className="flex items-center gap-2"
27
+ >
28
+ <Pencil className="h-4 w-4" />
29
+ Edit Task
30
+ </Button>
31
+ </div>
32
+
33
+ <TaskEdit
34
+ open={editOpen}
35
+ close={() => setEditOpen(false)}
36
+ taskId={record.id}
37
+ />
38
+
39
+ <AsideSection title="Task Info">
40
+ <InfoRow
41
+ icon={<Calendar className="w-4 h-4 text-muted-foreground" />}
42
+ label="Due Date"
43
+ value={<DateField source="due_date" />}
44
+ />
45
+ {record.done_date && (
46
+ <InfoRow
47
+ icon={<Calendar className="w-4 h-4 text-muted-foreground" />}
48
+ label="Completed"
49
+ value={<DateField source="done_date" />}
50
+ />
51
+ )}
52
+ </AsideSection>
53
+
54
+ <AsideSection title="Related">
55
+ <InfoRow
56
+ icon={<UserCircle className="w-4 h-4 text-muted-foreground" />}
57
+ label="Contact"
58
+ value={
59
+ <ReferenceField
60
+ source="contact_id"
61
+ reference="contacts"
62
+ link="show"
63
+ />
64
+ }
65
+ />
66
+ <InfoRow
67
+ icon={<Building2 className="w-4 h-4 text-muted-foreground" />}
68
+ label="Company"
69
+ value={
70
+ <ReferenceField source="contact_id" reference="contacts" link={false}>
71
+ <ReferenceField source="company_id" reference="companies" link="show">
72
+ <TextField source="name" />
73
+ </ReferenceField>
74
+ </ReferenceField>
75
+ }
76
+ />
77
+ </AsideSection>
78
+
79
+ <AsideSection title="Assignment">
80
+ <InfoRow
81
+ icon={<UserCheck className="w-4 h-4 text-muted-foreground" />}
82
+ label="Assigned To"
83
+ value={
84
+ <ReferenceField source="assigned_to" reference="sales" link={false} />
85
+ }
86
+ />
87
+ <InfoRow
88
+ icon={<UserCircle className="w-4 h-4 text-muted-foreground" />}
89
+ label="Created By"
90
+ value={
91
+ <ReferenceField source="sales_id" reference="sales" link={false} />
92
+ }
93
+ />
94
+ </AsideSection>
95
+
96
+ <div className="mt-6 pt-6 border-t hidden sm:flex flex-col gap-2 items-start">
97
+ <DeleteButton
98
+ className="h-6 cursor-pointer hover:bg-destructive/10! text-destructive! border-destructive! focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40"
99
+ size="sm"
100
+ />
101
+ </div>
102
+ </div>
103
+ );
104
+ };
105
+
106
+ const InfoRow = ({
107
+ icon,
108
+ label,
109
+ value,
110
+ }: {
111
+ icon: ReactNode;
112
+ label: string;
113
+ value: ReactNode;
114
+ }) => (
115
+ <div className="flex flex-col gap-1 mb-3">
116
+ <div className="flex items-center gap-2">
117
+ {icon}
118
+ <span className="text-xs text-muted-foreground">{label}</span>
119
+ </div>
120
+ <div className="pl-6 text-sm">{value}</div>
121
+ </div>
122
+ );
@@ -0,0 +1,112 @@
1
+ import { AutocompleteInput } from "@/components/admin/autocomplete-input";
2
+ import { DateInput } from "@/components/admin/date-input";
3
+ import { ReferenceInput } from "@/components/admin/reference-input";
4
+ import { SelectInput } from "@/components/admin/select-input";
5
+ import { TextInput } from "@/components/admin/text-input";
6
+ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
7
+ import { Create } from "@/components/admin/create";
8
+ import {
9
+ Form,
10
+ required,
11
+ useGetIdentity,
12
+ useNotify,
13
+ useRedirect,
14
+ } from "ra-core";
15
+
16
+ import { FormToolbar } from "../layout/FormToolbar";
17
+ import { contactOptionText } from "../misc/ContactOption";
18
+ import { useConfigurationContext } from "../root/ConfigurationContext";
19
+
20
+ export const TaskCreate = () => {
21
+ const { identity } = useGetIdentity();
22
+ const { taskTypes, taskPriorities, taskStatuses } = useConfigurationContext();
23
+ const notify = useNotify();
24
+ const redirect = useRedirect();
25
+
26
+ const handleSuccess = () => {
27
+ notify("Task created");
28
+ redirect("list", "tasks");
29
+ };
30
+
31
+ return (
32
+ <div className="mt-4 max-w-2xl mx-auto">
33
+ <Card>
34
+ <CardHeader>
35
+ <CardTitle>Create Task</CardTitle>
36
+ </CardHeader>
37
+ <CardContent>
38
+ <Create
39
+ resource="tasks"
40
+ redirect="list"
41
+ mutationOptions={{ onSuccess: handleSuccess }}
42
+ transform={(data) => ({
43
+ ...data,
44
+ sales_id: identity?.id,
45
+ created_at: new Date().toISOString(),
46
+ updated_at: new Date().toISOString(),
47
+ })}
48
+ >
49
+ <Form
50
+ defaultValues={{
51
+ due_date: new Date().toISOString().slice(0, 10),
52
+ priority: "medium",
53
+ status: "todo",
54
+ assigned_to: identity?.id,
55
+ }}
56
+ >
57
+ <TextInput
58
+ autoFocus
59
+ source="text"
60
+ label="Description"
61
+ validate={required()}
62
+ multiline
63
+ className="w-full"
64
+ />
65
+ <div className="grid grid-cols-2 gap-4 mt-4">
66
+ <ReferenceInput
67
+ source="contact_id"
68
+ reference="contacts_summary"
69
+ >
70
+ <AutocompleteInput
71
+ label="Contact"
72
+ optionText={contactOptionText}
73
+ validate={required()}
74
+ />
75
+ </ReferenceInput>
76
+ <DateInput
77
+ source="due_date"
78
+ validate={required()}
79
+ />
80
+ <SelectInput
81
+ source="type"
82
+ validate={required()}
83
+ choices={taskTypes.map((type) => ({
84
+ id: type,
85
+ name: type,
86
+ }))}
87
+ />
88
+ <SelectInput
89
+ source="priority"
90
+ choices={taskPriorities}
91
+ />
92
+ <SelectInput
93
+ source="status"
94
+ choices={taskStatuses}
95
+ />
96
+ <ReferenceInput source="assigned_to" reference="sales">
97
+ <SelectInput
98
+ optionText={(record) =>
99
+ `${record.first_name} ${record.last_name}`
100
+ }
101
+ label="Assigned To"
102
+ />
103
+ </ReferenceInput>
104
+ </div>
105
+ <FormToolbar />
106
+ </Form>
107
+ </Create>
108
+ </CardContent>
109
+ </Card>
110
+ </div>
111
+ );
112
+ };
@@ -3,6 +3,7 @@ import { DeleteButton } from "@/components/admin/delete-button";
3
3
  import { TextInput } from "@/components/admin/text-input";
4
4
  import { DateInput } from "@/components/admin/date-input";
5
5
  import { SelectInput } from "@/components/admin/select-input";
6
+ import { ReferenceInput } from "@/components/admin/reference-input";
6
7
  import { SaveButton } from "@/components/admin/form";
7
8
  import {
8
9
  Dialog,
@@ -23,7 +24,7 @@ export const TaskEdit = ({
23
24
  open: boolean;
24
25
  close: () => void;
25
26
  }) => {
26
- const { taskTypes } = useConfigurationContext();
27
+ const { taskTypes, taskPriorities, taskStatuses } = useConfigurationContext();
27
28
  const notify = useNotify();
28
29
  return (
29
30
  <Dialog open={open} onOpenChange={close}>
@@ -71,6 +72,24 @@ export const TaskEdit = ({
71
72
  helperText={false}
72
73
  validate={required()}
73
74
  />
75
+ <SelectInput
76
+ source="priority"
77
+ choices={taskPriorities}
78
+ helperText={false}
79
+ />
80
+ <SelectInput
81
+ source="status"
82
+ choices={taskStatuses}
83
+ helperText={false}
84
+ />
85
+ <ReferenceInput source="assigned_to" reference="sales">
86
+ <SelectInput
87
+ optionText={(record) =>
88
+ `${record.first_name} ${record.last_name}`
89
+ }
90
+ label="Assigned To"
91
+ />
92
+ </ReferenceInput>
74
93
  </div>
75
94
  <DialogFooter className="w-full sm:justify-between gap-4">
76
95
  <DeleteButton
@@ -0,0 +1,52 @@
1
+ import { AutocompleteInput } from "@/components/admin/autocomplete-input";
2
+ import { BooleanInput } from "@/components/admin/boolean-input";
3
+ import { CreateButton } from "@/components/admin/create-button";
4
+ import { ExportButton } from "@/components/admin/export-button";
5
+ import { FilterButton } from "@/components/admin/filter-form";
6
+ import { List } from "@/components/admin/list";
7
+ import { ReferenceInput } from "@/components/admin/reference-input";
8
+ import { SearchInput } from "@/components/admin/search-input";
9
+ import { SelectInput } from "@/components/admin/select-input";
10
+
11
+ import { useConfigurationContext } from "../root/ConfigurationContext";
12
+ import { TopToolbar } from "../layout/TopToolbar";
13
+ import { MyTasksInput } from "./MyTasksInput";
14
+ import { TaskListTable } from "./TaskListTable";
15
+
16
+ const TaskList = () => {
17
+ const { taskStatuses, taskPriorities } = useConfigurationContext();
18
+
19
+ const taskFilters = [
20
+ <SearchInput source="q" alwaysOn />,
21
+ <SelectInput source="status" choices={taskStatuses} alwaysOn />,
22
+ <ReferenceInput source="contact_id" reference="contacts">
23
+ <AutocompleteInput label={false} placeholder="Contact" />
24
+ </ReferenceInput>,
25
+ <SelectInput source="priority" choices={taskPriorities} />,
26
+ <MyTasksInput source="assigned_to" label="My Tasks" alwaysOn />,
27
+ <BooleanInput source="archived" label="Archived" />,
28
+ ];
29
+
30
+ return (
31
+ <List
32
+ perPage={25}
33
+ sort={{ field: "due_date", order: "ASC" }}
34
+ filters={taskFilters}
35
+ filterDefaultValues={{ archived: false }}
36
+ actions={<TaskActions />}
37
+ title="Tasks"
38
+ >
39
+ <TaskListTable />
40
+ </List>
41
+ );
42
+ };
43
+
44
+ const TaskActions = () => (
45
+ <TopToolbar>
46
+ <FilterButton />
47
+ <ExportButton />
48
+ <CreateButton label="New Task" />
49
+ </TopToolbar>
50
+ );
51
+
52
+ export default TaskList;
@@ -0,0 +1,60 @@
1
+ import { DataTable } from "@/components/admin/data-table";
2
+ import { DateField } from "@/components/admin/date-field";
3
+ import { ReferenceField } from "@/components/admin/reference-field";
4
+ import { TextField } from "@/components/admin/text-field";
5
+
6
+ import type { Task } from "../types";
7
+ import { TaskPriorityBadge } from "./TaskPriorityBadge";
8
+ import { TaskStatusBadge } from "./TaskStatusBadge";
9
+
10
+ export const TaskListTable = () => {
11
+ return (
12
+ <DataTable rowClick="show">
13
+ <DataTable.Col
14
+ source="text"
15
+ label="Task"
16
+ className="w-[35%]"
17
+ cellClassName="max-w-md"
18
+ render={(record: Task) => (
19
+ <div className="truncate" title={record.text}>
20
+ {record.type && record.type !== "None" && (
21
+ <span className="font-semibold">{record.type}: </span>
22
+ )}
23
+ {record.text}
24
+ </div>
25
+ )}
26
+ />
27
+ <DataTable.Col label="Contact" className="w-[15%]">
28
+ <ReferenceField source="contact_id" reference="contacts" link="show" />
29
+ </DataTable.Col>
30
+ <DataTable.Col label="Company" className="w-[15%]">
31
+ <ReferenceField
32
+ source="company_id"
33
+ reference="companies"
34
+ link="show"
35
+ sortable={false}
36
+ >
37
+ <TextField source="name" />
38
+ </ReferenceField>
39
+ </DataTable.Col>
40
+ <DataTable.Col label="Due Date" className="w-[12%]">
41
+ <DateField source="due_date" />
42
+ </DataTable.Col>
43
+ <DataTable.Col
44
+ label="Priority"
45
+ className="w-[10%]"
46
+ render={(record: Task) => (
47
+ <TaskPriorityBadge priority={record.priority} />
48
+ )}
49
+ />
50
+ <DataTable.Col
51
+ label="Status"
52
+ className="w-[10%]"
53
+ render={(record: Task) => <TaskStatusBadge status={record.status} />}
54
+ />
55
+ <DataTable.Col label="Assigned To" className="w-[13%]">
56
+ <ReferenceField source="assigned_to" reference="sales" link={false} />
57
+ </DataTable.Col>
58
+ </DataTable>
59
+ );
60
+ };
@@ -0,0 +1,20 @@
1
+ import { Badge } from "@/components/ui/badge";
2
+ import { cn } from "@/lib/utils";
3
+
4
+ const priorityColors = {
5
+ low: "bg-slate-500 hover:bg-slate-600",
6
+ medium: "bg-blue-500 hover:bg-blue-600",
7
+ high: "bg-orange-500 hover:bg-orange-600",
8
+ urgent: "bg-red-500 hover:bg-red-600",
9
+ };
10
+
11
+ export const TaskPriorityBadge = ({ priority }: { priority?: string }) => {
12
+ if (!priority) return null;
13
+ const colorClass = priorityColors[priority as keyof typeof priorityColors] || "bg-slate-500";
14
+
15
+ return (
16
+ <Badge className={cn("capitalize", colorClass)}>
17
+ {priority}
18
+ </Badge>
19
+ );
20
+ };
@@ -0,0 +1,71 @@
1
+ import { ShowBase, useShowContext } from "ra-core";
2
+ import { Card, CardContent } from "@/components/ui/card";
3
+ import { ReferenceManyField } from "@/components/admin/reference-many-field";
4
+
5
+ import { NoteCreate, NotesIterator } from "../notes";
6
+ import type { Task } from "../types";
7
+ import { TaskAside } from "./TaskAside";
8
+ import { TaskPriorityBadge } from "./TaskPriorityBadge";
9
+ import { TaskStatusBadge } from "./TaskStatusBadge";
10
+ import { TaskActivityTimeline } from "./TaskActivityTimeline";
11
+
12
+ export const TaskShow = () => (
13
+ <ShowBase>
14
+ <TaskShowContent />
15
+ </ShowBase>
16
+ );
17
+
18
+ const TaskShowContent = () => {
19
+ const { record, isPending } = useShowContext<Task>();
20
+ if (isPending || !record) return null;
21
+
22
+ return (
23
+ <div className="mt-2 mb-2 flex gap-8">
24
+ <div className="flex-1">
25
+ <Card>
26
+ <CardContent>
27
+ {/* Task Header */}
28
+ <div className="mb-6">
29
+ <h5 className="text-xl font-semibold mb-3">{record.type}</h5>
30
+ <div className="flex gap-3 mb-4">
31
+ <TaskStatusBadge status={record.status} />
32
+ <TaskPriorityBadge priority={record.priority} />
33
+ </div>
34
+ {record.text && (
35
+ <p className="text-sm text-muted-foreground whitespace-pre-line">
36
+ {record.text}
37
+ </p>
38
+ )}
39
+ </div>
40
+
41
+ {/* Activity Timeline */}
42
+ <div className="mt-8">
43
+ <h3 className="text-lg font-semibold mb-4">Activity Timeline</h3>
44
+ <p className="text-sm text-muted-foreground mb-3">
45
+ Track all status changes and updates for this task
46
+ </p>
47
+ <TaskActivityTimeline taskId={record.id} />
48
+ </div>
49
+
50
+ {/* Notes */}
51
+ <div className="mt-8">
52
+ <h3 className="text-lg font-semibold mb-4">Notes</h3>
53
+ <p className="text-sm text-muted-foreground mb-3">
54
+ Add notes and updates to this task
55
+ </p>
56
+ <ReferenceManyField
57
+ reference="taskNotes"
58
+ target="task_id"
59
+ sort={{ field: "date", order: "DESC" }}
60
+ empty={<NoteCreate reference="tasks" showStatus className="mt-4" />}
61
+ >
62
+ <NotesIterator reference="tasks" showStatus />
63
+ </ReferenceManyField>
64
+ </div>
65
+ </CardContent>
66
+ </Card>
67
+ </div>
68
+ <TaskAside />
69
+ </div>
70
+ );
71
+ };
@@ -0,0 +1,21 @@
1
+ import { Badge } from "@/components/ui/badge";
2
+ import { cn } from "@/lib/utils";
3
+
4
+ const statusColors = {
5
+ todo: "bg-slate-500 hover:bg-slate-600",
6
+ in_progress: "bg-blue-500 hover:bg-blue-600",
7
+ blocked: "bg-red-500 hover:bg-red-600",
8
+ done: "bg-green-500 hover:bg-green-600",
9
+ cancelled: "bg-gray-400 hover:bg-gray-500",
10
+ };
11
+
12
+ export const TaskStatusBadge = ({ status }: { status?: string }) => {
13
+ if (!status) return null;
14
+ const colorClass = statusColors[status as keyof typeof statusColors] || "bg-slate-500";
15
+
16
+ return (
17
+ <Badge className={cn("capitalize", colorClass)}>
18
+ {status.replace("_", " ")}
19
+ </Badge>
20
+ );
21
+ };
@@ -0,0 +1,9 @@
1
+ import { TaskCreate } from "./TaskCreate";
2
+ import TaskList from "./TaskList";
3
+ import { TaskShow } from "./TaskShow";
4
+
5
+ export default {
6
+ list: TaskList,
7
+ show: TaskShow,
8
+ create: TaskCreate,
9
+ };
@@ -216,6 +216,15 @@ export type Tag = {
216
216
  color: string;
217
217
  } & Pick<RaRecord, "id">;
218
218
 
219
+ export type TaskPriority = "low" | "medium" | "high" | "urgent";
220
+
221
+ export type TaskStatus =
222
+ | "todo"
223
+ | "in_progress"
224
+ | "blocked"
225
+ | "done"
226
+ | "cancelled";
227
+
219
228
  export type Task = {
220
229
  contact_id: Identifier;
221
230
  type: string;
@@ -223,6 +232,47 @@ export type Task = {
223
232
  due_date: string;
224
233
  done_date?: string | null;
225
234
  sales_id?: Identifier;
235
+ priority?: TaskPriority;
236
+ assigned_to?: Identifier;
237
+ status?: TaskStatus;
238
+ created_at?: string;
239
+ updated_at?: string;
240
+ archived?: boolean;
241
+ archived_at?: string;
242
+ } & Pick<RaRecord, "id">;
243
+
244
+ export type TaskSummary = Task & {
245
+ contact_first_name?: string;
246
+ contact_last_name?: string;
247
+ contact_email?: string;
248
+ company_id?: Identifier;
249
+ company_name?: string;
250
+ assigned_first_name?: string;
251
+ assigned_last_name?: string;
252
+ creator_first_name?: string;
253
+ creator_last_name?: string;
254
+ nb_notes?: number;
255
+ last_note_date?: string;
256
+ };
257
+
258
+ export type TaskNote = {
259
+ task_id: Identifier;
260
+ text: string;
261
+ date: string;
262
+ sales_id: Identifier;
263
+ status?: string;
264
+ created_at?: string;
265
+ updated_at?: string;
266
+ } & Pick<RaRecord, "id">;
267
+
268
+ export type TaskActivity = {
269
+ task_id: Identifier;
270
+ sales_id: Identifier;
271
+ action: string;
272
+ field_name?: string;
273
+ old_value?: string;
274
+ new_value?: string;
275
+ created_at: string;
226
276
  } & Pick<RaRecord, "id">;
227
277
 
228
278
  export type ActivityCompanyCreated = {
@@ -0,0 +1,10 @@
1
+ import * as React from "react"
2
+ import * as VisuallyHiddenPrimitive from "@radix-ui/react-visually-hidden"
3
+
4
+ function VisuallyHidden({
5
+ ...props
6
+ }: React.ComponentProps<typeof VisuallyHiddenPrimitive.Root>) {
7
+ return <VisuallyHiddenPrimitive.Root data-slot="visually-hidden" {...props} />
8
+ }
9
+
10
+ export { VisuallyHidden }