eletrotupi / tcc/ frontend/lib/history/mappers.tsc121404b00d29de6d91827ce3a3fc0ede1a0c5ab
4.6 KB | 162 lines Raw
1
import type { HistoryCard } from "@/lib/history/types";
2
import type { MoodEntry, SleepRecord, Trigger, CareAction } from "@/lib/api";
3
import { getMood } from "@/constants/moods";
4
import { parseDateOnly } from "@/lib/utils/time";
5

6

7
export function mapMoodToHistoryCard(mood: MoodEntry): HistoryCard {
8
  const moodLabel = getMood(mood.selectedMood);
9
  const components = mood.moodComponents
10
    .map((c) => c.component.charAt(0) + c.component.slice(1).toLowerCase())
11
    .join(", ");
12

13
  const summary = [components || null, mood.annotation || null]
14
    .filter(Boolean)
15
    .join(" · ");
16

17
  return {
18
    id: `mood-${mood.id}`,
19
    category: "mood",
20
    timestamp: mood.moment.toString(),
21
    title: moodLabel?.label ?? "Humor",
22
    summary: summary || "Sem detalhes",
23
    badge: undefined,
24
    raw: mood,
25
  };
26
}
27

28
// Sleep Records
29

30
function sleepQualityBadge(hours: number): HistoryCard["badge"] {
31
  if (hours >= 7) return { label: "Excelente", variant: "green" };
32
  if (hours >= 5) return { label: "Regular", variant: "yellow" };
33

34
  return {
35
    label: "Ruim",
36
    variant: "red",
37
  };
38
}
39

40
export function mapSleepToHistoryCard(record: SleepRecord): HistoryCard {
41
  const totalMinutes = Math.round(record.average * 60);
42
  const hours = Math.floor(totalMinutes / 60);
43
  const minutes = totalMinutes % 60;
44
  const duration = `${hours}h ${minutes.toString().padStart(2, "0")}min`;
45

46
  return {
47
    id: `sleep-${record.id}`,
48
    category: "sleep",
49
    timestamp: parseDateOnly(record.date).toISOString(),
50
    title: "Sono",
51
    summary: [duration, record.annotations].filter(Boolean).join(" · "),
52
    badge: sleepQualityBadge(record.average),
53
    raw: record,
54
  };
55
}
56

57
export function mapTriggerToHistoryCard(record: Trigger): HistoryCard {
58
  return {
59
    id: `trigger-${record.id}`,
60
    category: "trigger",
61
    timestamp: record.moment.toString(),
62
    title: "Gatilho",
63
    summary: [record.category, record.comment].filter(Boolean).join(" · "),
64
    badge: undefined,
65
    raw: record,
66
  };
67
}
68

69
function activityLabel(type?: string): string {
70
  const labels: Record<string, string> = {
71
    WALK: "Caminhada",
72
    YOGA: "Yoga",
73
    GYM: "Academia",
74
    MEDITATION: "Meditação",
75
    SOCIAL: "Momento social",
76
    CREATIVE: "Atividade criativa",
77
    OTHER: "Atividade",
78
  };
79
  return type ? (labels[type] ?? "Atividade") : "Atividade";
80
}
81

82
function appointmentLabel(type?: string): string {
83
  const labels: Record<string, string> = {
84
    ANALYST: "Analista",
85
    PSYCHIATRIST: "Psiquiatra",
86
    GP: "Clínico geral",
87
    NUTRITIONIST: "Nutricionista",
88
    PHYSIOTHERAPIST: "Fisioterapeuta",
89
    OTHER: "Consulta",
90
  };
91
  return type ? (labels[type] ?? "Consulta") : "Consulta";
92
}
93

94
export function mapCareActionToHistoryCard(record: CareAction): HistoryCard {
95
  switch (record.type) {
96
    case "MEDICINE": {
97
      const log = record.medicineLog;
98
      const name = log?.regimen?.name ?? "Medicamento";
99
      const dosage = log?.regimen?.dosage;
100
      return {
101
        id: `care_action-${record.id}`,
102
        category: "care_action",
103
        subtype: "medicine",
104
        timestamp: record.moment.toString(),
105
        title: name,
106
        summary: dosage ?? "Sem dosagem registrada",
107
        raw: record,
108
      };
109
    }
110

111
    case "APPOINTMENT": {
112
      const appt = record.appointment;
113
      const parts = [
114
        appt?.duration ? `${appt.duration} min` : null,
115
        appt?.note ?? null,
116
      ].filter(Boolean);
117
      const linkedCount =
118
        (record.triggerId ? 1 : 0) + (record.moodId ? 1 : 0);
119
      return {
120
        id: `care_action-${record.id}`,
121
        category: "care_action",
122
        subtype: "appointment",
123
        timestamp: record.moment.toString(),
124
        title: `Consulta · ${appointmentLabel(appt?.type)}`,
125
        summary: parts.join(" · ") || "Sem anotações",
126
        badge:
127
          linkedCount > 0
128
            ? {
129
                label: `${linkedCount} vínculo${linkedCount > 1 ? "s" : ""}`,
130
                variant: "blue",
131
              }
132
            : undefined,
133
        raw: record,
134
      };
135
    }
136

137
    case "ACTIVITY": {
138
      const act = record.activity;
139
      return {
140
        id: `care_action-${record.id}`,
141
        category: "care_action",
142
        subtype: "activity",
143
        timestamp: record.moment.toString(),
144
        title: activityLabel(act?.type),
145
        summary: act?.duration
146
          ? `${act.duration} min`
147
          : "Sem duração registrada",
148
        raw: record,
149
      };
150
    }
151

152
    default:
153
      return {
154
        id: `care_action-${record.id}`,
155
        category: "care_action",
156
        timestamp: record.moment.toString(),
157
        title: "Ação de cuidado",
158
        summary: "",
159
        raw: record,
160
      };
161
  }
162
}