eletrotupi / tcc/ frontend/components/medicine/MedicineRegimenList.tsx00a1c753d286aaa005996dc78a2911f038825877
3.7 KB | 120 lines Raw
1
import { View, Text, Switch, TouchableOpacity, StyleSheet, ActivityIndicator } from "react-native";
2
import { Ionicons } from "@expo/vector-icons";
3
import { router } from "expo-router";
4
import { Colors, Typography, Spacing, BorderRadius, Shadows } from "@/constants/theme";
5
import { useMedicineRegimens, useToggleMedicineRegimen } from "@/hooks";
6
import { MedicineRegimen } from "@/lib/api";
7

8
const PERIODICITY_LABELS: Record<string, string> = {
9
  ONCE: "Uma vez",
10
  DAILY: "Diário",
11
  TWICE_DAILY: "2x ao dia",
12
  THREE_TIMES_DAILY: "3x ao dia",
13
  WEEKLY: "Semanal",
14
  BIWEEKLY: "Quinzenal",
15
  MONTHLY: "Mensal",
16
};
17

18
function scheduleSummary(regimen: MedicineRegimen): string {
19
  const times = regimen.scheduledAt.length > 0
20
    ? regimen.scheduledAt.join(" · ")
21
    : null;
22
  const label = PERIODICITY_LABELS[regimen.periodicity] ?? regimen.periodicity;
23
  return times ? `${times} · ${label}` : label;
24
}
25

26
export function MedicineRegimenList() {
27
  const { data, isLoading } = useMedicineRegimens();
28
  const toggleRegimen = useToggleMedicineRegimen();
29

30
  if (isLoading) {
31
    return (
32
      <View style={styles.center}>
33
        <ActivityIndicator color={Colors.light.tint} />
34
      </View>
35
    );
36
  }
37

38
  const regimens = data?.regimens ?? [];
39

40
  return (
41
    <View style={styles.container}>
42
      {regimens.length === 0 ? (
43
        <View style={styles.empty}>
44
          <Text style={styles.emptyText}>Nenhum medicamento cadastrado</Text>
45
        </View>
46
      ) : (
47
        regimens.map((regimen) => (
48
          <TouchableOpacity
49
            key={regimen.id}
50
            style={styles.row}
51
            activeOpacity={0.7}
52
            onPress={() => router.push(`/medicine-regimens/${regimen.id}`)}
53
          >
54
            <View style={styles.iconWrap}>
55
              <Ionicons name="bandage-outline" size={18} color={Colors.light.tint} />
56
            </View>
57
            <View style={styles.info}>
58
              <Text style={styles.name}>{regimen.name}</Text>
59
              <Text style={styles.meta}>
60
                {regimen.dosage} · {scheduleSummary(regimen)}
61
              </Text>
62
            </View>
63
            <Switch
64
              value={regimen.active}
65
              onValueChange={(val) =>
66
                toggleRegimen.mutate({ id: String(regimen.id), active: val })
67
              }
68
              trackColor={{ true: Colors.light.tint, false: Colors.light.divider }}
69
              thumbColor="#fff"
70
            />
71
          </TouchableOpacity>
72
        ))
73
      )}
74

75
      <TouchableOpacity
76
        style={styles.addButton}
77
        activeOpacity={0.7}
78
        onPress={() => router.push("/care-actions/medicine-new")}
79
      >
80
        <Ionicons name="add-circle-outline" size={18} color={Colors.light.tint} />
81
        <Text style={styles.addText}>Adicionar medicamento</Text>
82
      </TouchableOpacity>
83
    </View>
84
  );
85
}
86

87
const styles = StyleSheet.create({
88
  container: { gap: 1 },
89
  center: { padding: Spacing.cardGap, alignItems: "center" },
90
  empty: { padding: Spacing.cardGap },
91
  emptyText: { ...Typography.bodyMd, color: Colors.light.textSecondary },
92
  row: {
93
    flexDirection: "row",
94
    alignItems: "center",
95
    backgroundColor: "#fff",
96
    padding: Spacing.cardGap,
97
    gap: 12,
98
    ...Shadows.sm,
99
    borderRadius: BorderRadius.lg,
100
  },
101
  iconWrap: {
102
    width: 32,
103
    height: 32,
104
    borderRadius: BorderRadius.md,
105
    backgroundColor: Colors.light.tint + "1A",
106
    alignItems: "center",
107
    justifyContent: "center",
108
  },
109
  info: { flex: 1 },
110
  name: { ...Typography.bodyMd, fontWeight: "600" },
111
  meta: { ...Typography.labelSm, color: Colors.light.textSecondary },
112
  addButton: {
113
    flexDirection: "row",
114
    alignItems: "center",
115
    gap: 8,
116
    paddingVertical: Spacing.cardGap,
117
    paddingHorizontal: 4,
118
  },
119
  addText: { ...Typography.bodyMd, color: Colors.light.tint, fontWeight: "600" },
120
});