@hed-hog/contact 0.0.285 → 0.0.291

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.
@@ -100,11 +100,25 @@ function usePersonFieldWithCreateTranslations() {
100
100
  values?: Record<string, string | number | boolean | null | undefined>
101
101
  ) => {
102
102
  const contactKey = `contact.PersonFieldWithCreate.${key}`;
103
+ // Filter values to only include types compatible with next-intl
104
+ const filteredValues = values
105
+ ? Object.fromEntries(
106
+ Object.entries(values).filter(
107
+ ([_, v]) => typeof v === 'string' || typeof v === 'number'
108
+ )
109
+ )
110
+ : undefined;
103
111
  if (tRoot.has(contactKey)) {
104
- return tRoot(contactKey, values);
112
+ return tRoot(
113
+ contactKey,
114
+ filteredValues as Record<string, string | number> | undefined
115
+ );
105
116
  }
106
117
 
107
- return tRoot(`finance.PersonFieldWithCreate.${key}`, values);
118
+ return tRoot(
119
+ `finance.PersonFieldWithCreate.${key}`,
120
+ filteredValues as Record<string, string | number> | undefined
121
+ );
108
122
  };
109
123
  }
110
124
 
@@ -643,20 +657,22 @@ export function PersonFieldWithCreate<TFieldValues extends FieldValues>({
643
657
  params.set('search', debouncedPersonSearch.trim());
644
658
  }
645
659
 
646
- const response = await request<PaginatedResponse<PersonOption> | PersonOption[]>({
660
+ const response = await request<
661
+ PaginatedResponse<PersonOption> | PersonOption[]
662
+ >({
647
663
  url: `/person?${params.toString()}`,
648
664
  method: 'GET',
649
665
  });
650
666
 
651
667
  const payload = response?.data;
652
- if (Array.isArray(payload?.data)) {
653
- return payload.data as PersonOption[];
654
- }
655
-
656
668
  if (Array.isArray(payload)) {
657
669
  return payload as PersonOption[];
658
670
  }
659
671
 
672
+ if (payload && 'data' in payload && Array.isArray(payload.data)) {
673
+ return payload.data as PersonOption[];
674
+ }
675
+
660
676
  return [];
661
677
  },
662
678
  placeholderData: (old) => old ?? [],
@@ -670,7 +686,10 @@ export function PersonFieldWithCreate<TFieldValues extends FieldValues>({
670
686
  return (
671
687
  <>
672
688
  <div className="grid gap-2">
673
- <Label data-error={!!fieldState.error} className="data-[error=true]:text-destructive">
689
+ <Label
690
+ data-error={!!fieldState.error}
691
+ className="data-[error=true]:text-destructive"
692
+ >
674
693
  {label}
675
694
  </Label>
676
695
  <Controller
@@ -798,9 +817,7 @@ export function PersonFieldWithCreate<TFieldValues extends FieldValues>({
798
817
  }}
799
818
  />
800
819
  {fieldState.error?.message ? (
801
- <p className="text-destructive text-sm">
802
- {fieldState.error.message}
803
- </p>
820
+ <p className="text-destructive text-sm">{fieldState.error.message}</p>
804
821
  ) : null}
805
822
  </div>
806
823
 
@@ -8,7 +8,6 @@ import {
8
8
  PaginationFooter,
9
9
  SearchBar,
10
10
  type SearchBarControl,
11
- StatsCards,
12
11
  } from '@/components/entity-list';
13
12
  import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
14
13
  import { Badge } from '@/components/ui/badge';
@@ -21,6 +20,7 @@ import {
21
20
  DropdownMenuSeparator,
22
21
  DropdownMenuTrigger,
23
22
  } from '@/components/ui/dropdown-menu';
23
+ import { KpiCardsGrid } from '@/components/ui/kpi-cards-grid';
24
24
  import { Skeleton } from '@/components/ui/skeleton';
25
25
  import {
26
26
  Table,
@@ -714,32 +714,36 @@ export default function PeoplePage() {
714
714
 
715
715
  const statsCards = [
716
716
  {
717
+ key: 'total',
717
718
  title: t('statsTotal'),
718
719
  value: stats.total,
719
- icon: <Users className="h-5 w-5" />,
720
- iconBgColor: 'bg-slate-100',
721
- iconColor: 'text-slate-700',
720
+ icon: Users,
721
+ accentClassName: 'from-slate-500/20 via-slate-400/10 to-transparent',
722
+ iconContainerClassName: 'bg-slate-100 text-slate-700',
722
723
  },
723
724
  {
725
+ key: 'active',
724
726
  title: t('statsActive'),
725
727
  value: stats.active,
726
- icon: <CheckCircle2 className="h-5 w-5" />,
727
- iconBgColor: 'bg-green-50',
728
- iconColor: 'text-green-600',
728
+ icon: CheckCircle2,
729
+ accentClassName: 'from-green-500/20 via-emerald-500/10 to-transparent',
730
+ iconContainerClassName: 'bg-green-50 text-green-600',
729
731
  },
730
732
  {
733
+ key: 'individual',
731
734
  title: t('statsIndividual'),
732
735
  value: stats.individual,
733
- icon: <UserCheck className="h-5 w-5" />,
734
- iconBgColor: 'bg-blue-50',
735
- iconColor: 'text-blue-600',
736
+ icon: UserCheck,
737
+ accentClassName: 'from-blue-500/20 via-cyan-500/10 to-transparent',
738
+ iconContainerClassName: 'bg-blue-50 text-blue-600',
736
739
  },
737
740
  {
741
+ key: 'company',
738
742
  title: t('statsCompany'),
739
743
  value: stats.company,
740
- icon: <Building2 className="h-5 w-5" />,
741
- iconBgColor: 'bg-amber-50',
742
- iconColor: 'text-amber-600',
744
+ icon: Building2,
745
+ accentClassName: 'from-amber-500/20 via-orange-500/10 to-transparent',
746
+ iconContainerClassName: 'bg-amber-50 text-amber-600',
743
747
  },
744
748
  ];
745
749
 
@@ -807,7 +811,7 @@ export default function PeoplePage() {
807
811
  ]}
808
812
  />
809
813
 
810
- <StatsCards stats={statsCards} />
814
+ <KpiCardsGrid items={statsCards} />
811
815
 
812
816
  <div className="flex flex-col gap-4 xl:flex-row xl:items-center">
813
817
  <div className="flex-1">
@@ -1,19 +1,5 @@
1
1
  'use client';
2
2
 
3
- import {
4
- closestCenter,
5
- DndContext,
6
- DragOverlay,
7
- PointerSensor,
8
- useDraggable,
9
- useDroppable,
10
- useSensor,
11
- useSensors,
12
- type DragEndEvent,
13
- type DragStartEvent,
14
- type UniqueIdentifier,
15
- } from '@dnd-kit/core';
16
- import { CSS } from '@dnd-kit/utilities';
17
3
  import {
18
4
  Page,
19
5
  PageHeader,
@@ -21,7 +7,6 @@ import {
21
7
  type SearchBarControl,
22
8
  } from '@/components/entity-list';
23
9
  import { Badge } from '@/components/ui/badge';
24
- import { Button } from '@/components/ui/button';
25
10
  import {
26
11
  Card,
27
12
  CardContent,
@@ -34,6 +19,7 @@ import {
34
19
  CollapsibleContent,
35
20
  CollapsibleTrigger,
36
21
  } from '@/components/ui/collapsible';
22
+ import { KpiCardsGrid } from '@/components/ui/kpi-cards-grid';
37
23
  import { ScrollArea } from '@/components/ui/scroll-area';
38
24
  import {
39
25
  Tooltip,
@@ -42,6 +28,20 @@ import {
42
28
  } from '@/components/ui/tooltip';
43
29
  import { useDebounce } from '@/hooks/use-debounce';
44
30
  import { cn } from '@/lib/utils';
31
+ import {
32
+ closestCenter,
33
+ DndContext,
34
+ DragOverlay,
35
+ PointerSensor,
36
+ useDraggable,
37
+ useDroppable,
38
+ useSensor,
39
+ useSensors,
40
+ type DragEndEvent,
41
+ type DragStartEvent,
42
+ type UniqueIdentifier,
43
+ } from '@dnd-kit/core';
44
+ import { CSS } from '@dnd-kit/utilities';
45
45
  import { useApp, useQuery } from '@hed-hog/next-app-provider';
46
46
  import {
47
47
  CalendarCheck,
@@ -71,8 +71,9 @@ import {
71
71
  type ReactNode,
72
72
  } from 'react';
73
73
  import { toast } from 'sonner';
74
- import { crmImplementedSections } from '../_lib/crm-sections';
75
74
  import { crmStageOrder, type CrmLead } from '../_lib/crm-mocks';
75
+ import { crmImplementedSections } from '../_lib/crm-sections';
76
+ import { PersonFormSheet } from '../person/_components/person-form-sheet';
76
77
  import type {
77
78
  ContactTypeOption,
78
79
  DocumentTypeOption,
@@ -81,7 +82,6 @@ import type {
81
82
  PersonLifecycleStage,
82
83
  UserOption,
83
84
  } from '../person/_components/person-types';
84
- import { PersonFormSheet } from '../person/_components/person-form-sheet';
85
85
  import { LeadDetailSheet } from './_components/lead-detail-sheet';
86
86
 
87
87
  const PIPELINE_EXPANDED_KEY = 'contact:crm-pipeline:expanded-leads';
@@ -154,8 +154,6 @@ function DraggableLeadCard({
154
154
  'touch-none',
155
155
  isDragging && 'z-30 opacity-60 shadow-lg ring-1 ring-primary/30'
156
156
  )}
157
- role="button"
158
- tabIndex={0}
159
157
  onClick={onClick}
160
158
  onKeyDown={onKeyDown}
161
159
  {...listeners}
@@ -458,7 +456,24 @@ export default function CrmPipelinePage() {
458
456
  ),
459
457
  icon: CircleDollarSign,
460
458
  },
461
- ] as const;
459
+ ].map((item, index) => {
460
+ const sectionStyle =
461
+ crmImplementedSections[index % crmImplementedSections.length] ??
462
+ crmImplementedSections[0];
463
+
464
+ return {
465
+ key: item.key,
466
+ title: t(`summary.${item.key}.title`),
467
+ value: item.value,
468
+ description: t(`summary.${item.key}.description`, {
469
+ count: nextActions,
470
+ }),
471
+ icon: item.icon,
472
+ accentClassName: sectionStyle?.colorClass ?? fallbackKpiAccentClass,
473
+ iconContainerClassName:
474
+ sectionStyle?.glowClass ?? 'bg-sky-500/10 text-sky-700',
475
+ };
476
+ });
462
477
 
463
478
  const allExpanded =
464
479
  visibleLeads.length > 0 && visibleLeads.every((l) => expandedIds.has(l.id));
@@ -549,7 +564,8 @@ export default function CrmPipelinePage() {
549
564
  const sourceLead = visibleLeadsById.get(sourceLeadId);
550
565
  if (!sourceLead || sourceLead.lifecycle_stage === targetStage) return;
551
566
 
552
- const previousStage = sourceLead.lifecycle_stage;
567
+ const previousStage: PersonLifecycleStage =
568
+ sourceLead.lifecycle_stage ?? 'new';
553
569
 
554
570
  setStageOverrides((prev) => ({ ...prev, [sourceLeadId]: targetStage }));
555
571
  setSelectedLead((prev) =>
@@ -633,51 +649,8 @@ export default function CrmPipelinePage() {
633
649
  ]}
634
650
  />
635
651
 
636
- <div className="min-w-0 space-y-6 overflow-x-hidden">
637
- <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
638
- {kpiCards.map((item, index) => {
639
- const sectionStyle =
640
- crmImplementedSections[index % crmImplementedSections.length] ??
641
- crmImplementedSections[0];
642
-
643
- return (
644
- <Card
645
- key={item.key}
646
- className="min-w-0 overflow-hidden border-border/70 py-0"
647
- >
648
- <div
649
- className={cn(
650
- 'h-1 w-full bg-linear-to-r',
651
- sectionStyle?.colorClass ?? fallbackKpiAccentClass
652
- )}
653
- />
654
- <CardContent className="flex items-start justify-between gap-3 px-6 py-5">
655
- <div className="min-w-0">
656
- <p className="text-xs uppercase tracking-[0.2em] text-muted-foreground">
657
- {t(`summary.${item.key}.title`)}
658
- </p>
659
- <p className="mt-2 text-3xl font-semibold tracking-tight">
660
- {item.value}
661
- </p>
662
- <p className="mt-1 text-sm text-muted-foreground">
663
- {t(`summary.${item.key}.description`, {
664
- count: nextActions,
665
- })}
666
- </p>
667
- </div>
668
- <div
669
- className={cn(
670
- 'rounded-2xl p-3',
671
- sectionStyle?.glowClass ?? 'bg-sky-500/10 text-sky-700'
672
- )}
673
- >
674
- <item.icon className="size-5" />
675
- </div>
676
- </CardContent>
677
- </Card>
678
- );
679
- })}
680
- </div>
652
+ <div className="min-w-0 space-y-4 overflow-x-hidden">
653
+ <KpiCardsGrid items={kpiCards} />
681
654
 
682
655
  <SearchBar
683
656
  searchQuery={searchTerm}
@@ -184,9 +184,43 @@
184
184
  "duplicateMergeError": "Failed to merge records.",
185
185
  "owner": "Owner",
186
186
  "unassigned": "Unassigned",
187
+ "source": "Source",
188
+ "sourceReferral": "Referral",
189
+ "sourceWebsite": "Website",
190
+ "sourceSocial": "Social",
191
+ "sourceInbound": "Inbound",
192
+ "sourceOutbound": "Outbound",
193
+ "sourceOther": "Other",
194
+ "lifecycleStage": "Stage",
195
+ "lifecycleNew": "New",
196
+ "lifecycleContacted": "Contacted",
197
+ "lifecycleQualified": "Qualified",
198
+ "lifecycleProposal": "Proposal",
199
+ "lifecycleNegotiation": "Negotiation",
200
+ "lifecycleCustomer": "Customer",
201
+ "lifecycleLost": "Lost",
202
+ "nextActionAt": "Next action",
203
+ "nextActionEmpty": "No follow-up",
187
204
  "registerInteraction": "Register Interaction",
205
+ "registerInteractionDescription": "Register the latest contact made with this person.",
188
206
  "scheduleFollowup": "Schedule Follow-up",
207
+ "scheduleFollowupDescription": "Set the date and owner for the next action.",
189
208
  "interactionType": "Interaction Type",
209
+ "interactionTypeCall": "Call",
210
+ "interactionTypeEmail": "Email",
211
+ "interactionTypeWhatsapp": "WhatsApp",
212
+ "interactionTypeMeeting": "Meeting",
213
+ "interactionTypeNote": "Note",
214
+ "interactionDate": "Interaction date",
215
+ "interactionOutcome": "Outcome",
216
+ "interactionOutcomePlaceholder": "E.g. Interested, asked for a proposal...",
217
+ "interactionNotesPlaceholder": "Write a quick summary...",
218
+ "interactionCreateSuccess": "Interaction recorded successfully.",
219
+ "interactionCreateError": "Failed to record interaction.",
220
+ "nextActionRequired": "The next action date is required.",
221
+ "schedule": "Schedule",
222
+ "saveAndNew": "Save and new",
223
+ "formShortcutsHint": "Shortcuts: Ctrl/Cmd+S to save, Esc to close.",
190
224
  "interactionType_call": "Call",
191
225
  "interactionType_email": "Email",
192
226
  "interactionType_whatsapp": "WhatsApp",
@@ -610,6 +644,133 @@
610
644
  "age": "Days since first contact with this lead."
611
645
  }
612
646
  },
647
+ "CrmFollowups": {
648
+ "title": "Follow-ups",
649
+ "description": "Track upcoming actions, overdue items, and owner commitments in one operational list.",
650
+ "newFollowup": "New Follow-up",
651
+ "reschedule": "Reschedule",
652
+ "unassigned": "Unassigned",
653
+ "stats": {
654
+ "total": "Total follow-ups",
655
+ "today": "Due today",
656
+ "overdue": "Overdue",
657
+ "upcoming": "Upcoming"
658
+ },
659
+ "filters": {
660
+ "searchPlaceholder": "Search by lead, contact, or account name...",
661
+ "statusPlaceholder": "Status",
662
+ "statusAll": "All statuses"
663
+ },
664
+ "status": {
665
+ "today": "Today",
666
+ "upcoming": "Upcoming",
667
+ "overdue": "Overdue"
668
+ },
669
+ "table": {
670
+ "person": "Person",
671
+ "owner": "Owner",
672
+ "nextAction": "Next action",
673
+ "lastInteraction": "Last interaction",
674
+ "status": "Status",
675
+ "actions": "Actions"
676
+ },
677
+ "empty": {
678
+ "title": "No follow-ups found",
679
+ "description": "Adjust your filters or create a new follow-up to start managing next actions."
680
+ },
681
+ "sheet": {
682
+ "title": "Schedule follow-up",
683
+ "description": "Define person, date, and notes for the next action.",
684
+ "submit": "Save follow-up"
685
+ },
686
+ "form": {
687
+ "person": "Person",
688
+ "personPlaceholder": "Select a person",
689
+ "date": "Follow-up date",
690
+ "notes": "Notes",
691
+ "notesPlaceholder": "Add context for the next interaction...",
692
+ "personRequired": "Select a person.",
693
+ "dateRequired": "Set a date and time."
694
+ },
695
+ "toasts": {
696
+ "scheduleSuccess": "Follow-up scheduled successfully",
697
+ "scheduleError": "Failed to schedule follow-up"
698
+ },
699
+ "errors": {
700
+ "invalidPerson": "Invalid person.",
701
+ "invalidDate": "Invalid date."
702
+ }
703
+ },
704
+ "CrmActivities": {
705
+ "title": "Activities",
706
+ "description": "Operational activity queue with calls, meetings, messages, and tasks tracked by owner and due date.",
707
+ "viewMode": "View",
708
+ "viewModeTable": "Table",
709
+ "viewModeTimeline": "Timeline",
710
+ "unassignedPerson": "Unassigned lead",
711
+ "unassignedOwner": "Unassigned",
712
+ "stats": {
713
+ "total": "Total activities",
714
+ "pending": "Pending",
715
+ "overdue": "Overdue",
716
+ "completed": "Completed"
717
+ },
718
+ "filters": {
719
+ "searchPlaceholder": "Search by subject, lead, owner, or notes...",
720
+ "statusPlaceholder": "Status",
721
+ "typePlaceholder": "Type",
722
+ "priorityPlaceholder": "Priority",
723
+ "allStatuses": "All statuses",
724
+ "allTypes": "All types",
725
+ "allPriorities": "All priorities"
726
+ },
727
+ "status": {
728
+ "pending": "Pending",
729
+ "overdue": "Overdue",
730
+ "completed": "Completed"
731
+ },
732
+ "type": {
733
+ "call": "Call",
734
+ "email": "Email",
735
+ "meeting": "Meeting",
736
+ "whatsapp": "WhatsApp",
737
+ "task": "Task",
738
+ "note": "Note"
739
+ },
740
+ "priority": {
741
+ "high": "High",
742
+ "medium": "Medium",
743
+ "low": "Low"
744
+ },
745
+ "table": {
746
+ "activity": "Activity",
747
+ "person": "Lead / Contact",
748
+ "owner": "Owner",
749
+ "dueAt": "Due at",
750
+ "createdAt": "Created",
751
+ "status": "Status",
752
+ "priority": "Priority",
753
+ "actions": "Actions"
754
+ },
755
+ "actions": {
756
+ "view": "View",
757
+ "complete": "Mark done"
758
+ },
759
+ "timeline": {
760
+ "description": "Chronological timeline view of activities in the current filter.",
761
+ "dueLabel": "Due",
762
+ "createdLabel": "Created"
763
+ },
764
+ "empty": {
765
+ "title": "No activities found",
766
+ "description": "Adjust filters to find activities or clear filters to return to the full queue.",
767
+ "resetFilters": "Clear filters"
768
+ },
769
+ "toasts": {
770
+ "markedAsCompleted": "Activity marked as completed.",
771
+ "openDetails": "Opening activity: {subject}"
772
+ }
773
+ },
613
774
  "CrmFuturePage": {
614
775
  "breadcrumbs": {
615
776
  "home": "Home",
@@ -643,6 +643,133 @@
643
643
  "age": "Dias desde o primeiro contato com este lead."
644
644
  }
645
645
  },
646
+ "CrmFollowups": {
647
+ "title": "Follow-ups",
648
+ "description": "Acompanhe próximas ações, vencidos e compromissos por responsável em uma lista operacional.",
649
+ "newFollowup": "Novo Follow-up",
650
+ "reschedule": "Reagendar",
651
+ "unassigned": "Não atribuído",
652
+ "stats": {
653
+ "total": "Total de follow-ups",
654
+ "today": "Vencem hoje",
655
+ "overdue": "Vencidos",
656
+ "upcoming": "Próximos"
657
+ },
658
+ "filters": {
659
+ "searchPlaceholder": "Buscar por lead, contato ou conta...",
660
+ "statusPlaceholder": "Status",
661
+ "statusAll": "Todos os status"
662
+ },
663
+ "status": {
664
+ "today": "Hoje",
665
+ "upcoming": "Próximos",
666
+ "overdue": "Vencidos"
667
+ },
668
+ "table": {
669
+ "person": "Pessoa",
670
+ "owner": "Responsável",
671
+ "nextAction": "Próxima ação",
672
+ "lastInteraction": "Última interação",
673
+ "status": "Status",
674
+ "actions": "Ações"
675
+ },
676
+ "empty": {
677
+ "title": "Nenhum follow-up encontrado",
678
+ "description": "Ajuste os filtros ou crie um novo follow-up para começar a gerir as próximas ações."
679
+ },
680
+ "sheet": {
681
+ "title": "Agendar follow-up",
682
+ "description": "Defina pessoa, data e notas para a próxima ação.",
683
+ "submit": "Salvar follow-up"
684
+ },
685
+ "form": {
686
+ "person": "Pessoa",
687
+ "personPlaceholder": "Selecione uma pessoa",
688
+ "date": "Data do follow-up",
689
+ "notes": "Notas",
690
+ "notesPlaceholder": "Adicione contexto para a próxima interação...",
691
+ "personRequired": "Selecione uma pessoa.",
692
+ "dateRequired": "Defina data e hora."
693
+ },
694
+ "toasts": {
695
+ "scheduleSuccess": "Follow-up agendado com sucesso",
696
+ "scheduleError": "Falha ao agendar follow-up"
697
+ },
698
+ "errors": {
699
+ "invalidPerson": "Pessoa inválida.",
700
+ "invalidDate": "Data inválida."
701
+ }
702
+ },
703
+ "CrmActivities": {
704
+ "title": "Atividades",
705
+ "description": "Fila operacional de atividades com ligações, reuniões, mensagens e tarefas por responsável e prazo.",
706
+ "viewMode": "Visualização",
707
+ "viewModeTable": "Tabela",
708
+ "viewModeTimeline": "Timeline",
709
+ "unassignedPerson": "Lead não atribuído",
710
+ "unassignedOwner": "Não atribuído",
711
+ "stats": {
712
+ "total": "Total de atividades",
713
+ "pending": "Pendentes",
714
+ "overdue": "Atrasadas",
715
+ "completed": "Concluídas"
716
+ },
717
+ "filters": {
718
+ "searchPlaceholder": "Buscar por assunto, lead, responsável ou notas...",
719
+ "statusPlaceholder": "Status",
720
+ "typePlaceholder": "Tipo",
721
+ "priorityPlaceholder": "Prioridade",
722
+ "allStatuses": "Todos os status",
723
+ "allTypes": "Todos os tipos",
724
+ "allPriorities": "Todas as prioridades"
725
+ },
726
+ "status": {
727
+ "pending": "Pendente",
728
+ "overdue": "Atrasada",
729
+ "completed": "Concluída"
730
+ },
731
+ "type": {
732
+ "call": "Ligação",
733
+ "email": "E-mail",
734
+ "meeting": "Reunião",
735
+ "whatsapp": "WhatsApp",
736
+ "task": "Tarefa",
737
+ "note": "Anotação"
738
+ },
739
+ "priority": {
740
+ "high": "Alta",
741
+ "medium": "Média",
742
+ "low": "Baixa"
743
+ },
744
+ "table": {
745
+ "activity": "Atividade",
746
+ "person": "Lead / Contato",
747
+ "owner": "Responsável",
748
+ "dueAt": "Prazo",
749
+ "createdAt": "Criada em",
750
+ "status": "Status",
751
+ "priority": "Prioridade",
752
+ "actions": "Ações"
753
+ },
754
+ "actions": {
755
+ "view": "Ver",
756
+ "complete": "Concluir"
757
+ },
758
+ "timeline": {
759
+ "description": "Visão cronológica das atividades considerando os filtros atuais.",
760
+ "dueLabel": "Prazo",
761
+ "createdLabel": "Criada"
762
+ },
763
+ "empty": {
764
+ "title": "Nenhuma atividade encontrada",
765
+ "description": "Ajuste os filtros para encontrar atividades ou limpe os filtros para voltar à fila completa.",
766
+ "resetFilters": "Limpar filtros"
767
+ },
768
+ "toasts": {
769
+ "markedAsCompleted": "Atividade marcada como concluída.",
770
+ "openDetails": "Abrindo atividade: {subject}"
771
+ }
772
+ },
646
773
  "CrmFuturePage": {
647
774
  "breadcrumbs": {
648
775
  "home": "Home",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hed-hog/contact",
3
- "version": "0.0.285",
3
+ "version": "0.0.291",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "dependencies": {
@@ -9,13 +9,13 @@
9
9
  "@nestjs/core": "^11",
10
10
  "@nestjs/jwt": "^11",
11
11
  "@nestjs/mapped-types": "*",
12
- "@hed-hog/address": "0.0.285",
12
+ "@hed-hog/core": "0.0.291",
13
13
  "@hed-hog/api-mail": "0.0.8",
14
- "@hed-hog/core": "0.0.285",
15
- "@hed-hog/api": "0.0.4",
16
- "@hed-hog/api-pagination": "0.0.6",
17
14
  "@hed-hog/api-prisma": "0.0.5",
18
- "@hed-hog/api-locale": "0.0.13"
15
+ "@hed-hog/api-locale": "0.0.13",
16
+ "@hed-hog/address": "0.0.291",
17
+ "@hed-hog/api": "0.0.4",
18
+ "@hed-hog/api-pagination": "0.0.6"
19
19
  },
20
20
  "exports": {
21
21
  ".": {
@@ -16,7 +16,7 @@ export class ContactService {
16
16
  private readonly jwtService: JwtService,
17
17
  ) {}
18
18
 
19
- async getPerson(personId: number) {
19
+ async getPerson(personId: number): Promise<any> {
20
20
  const person = await this.prismaService.person.findUnique({
21
21
  where: {
22
22
  id: personId,
@@ -52,7 +52,7 @@ export class ContactService {
52
52
  phone: string,
53
53
  cpf: string,
54
54
  cnpj: string,
55
- ) {
55
+ ): Promise<any> {
56
56
  const findPersonByEmail = await this.prismaService.person.findFirst({
57
57
  where: {
58
58
  contact: {