eletrotupi / tcc/ frontend/app/care-actions/medicine-new.tsxea1475564abe0f26ea6bb9c6c840b714261aad91
6.2 KB | 203 lines Raw
1
import {
2
  View,
3
  StyleSheet,
4
  KeyboardAvoidingView,
5
  ScrollView,
6
  TouchableOpacity,
7
} from "react-native";
8
import { Text } from "@/components/ui/Text";
9
import { useState } from "react";
10
import { router } from "expo-router";
11

12
import { Card } from "@/components/ui/Cards";
13
import { Input } from "@/components/ui/Input";
14
import { Button } from "@/components/ui/Button";
15
import { Section, SectionHeader } from "@/components/ui/Sections";
16
import { Spacing, Typography, Colors, BorderRadius } from "@/constants/theme";
17
import { TimePicker } from "@/components/ui/TimePicker";
18
import { useCreateMedicineRegimen } from "@/hooks";
19
import { MedicinePeriodicity } from "@/lib/api";
20

21
const PERIODICITY_OPTIONS: { label: string; value: MedicinePeriodicity }[] = [
22
  { label: 'Uma vez', value: 'ONCE' },
23
  { label: 'Diário', value: 'DAILY' },
24
  { label: '2x ao dia', value: 'TWICE_DAILY' },
25
  { label: '3x ao dia', value: 'THREE_TIMES_DAILY' },
26
  { label: 'Semanal', value: 'WEEKLY' },
27
  { label: 'Quinzenal', value: 'BIWEEKLY' },
28
  { label: 'Mensal', value: 'MONTHLY' },
29
];
30

31
function getTimePickerCount(p: MedicinePeriodicity): number {
32
  switch (p) {
33
    case 'ONCE': return 0;
34
    case 'DAILY': return 1;
35
    case 'TWICE_DAILY': return 2;
36
    case 'THREE_TIMES_DAILY': return 3;
37
    default: return 1;
38
  }
39
}
40

41
export default function MedicineNewCareAction() {
42
  const [medicineName, setMedicineName] = useState('');
43
  const [medicineDosage, setMedicineDosage] = useState('');
44
  const [medicinePeriodicity, setMedicinePeriodicity] = useState<MedicinePeriodicity>('ONCE');
45
  const [scheduledTimes, setScheduledTimes] = useState<Date[]>([]);
46

47
  const createRegimen = useCreateMedicineRegimen();
48

49
  const handleSave = async () => {
50
    const count = getTimePickerCount(medicinePeriodicity);
51
    const scheduledAt = scheduledTimes.slice(0, count).map(
52
      d => `${d.getHours().toString().padStart(2,'0')}:${d.getMinutes().toString().padStart(2,'0')}`
53
    );
54

55
    await createRegimen.mutateAsync({
56
      name: medicineName,
57
      dosage: medicineDosage,
58
      periodicity: medicinePeriodicity,
59
      scheduledAt,
60
    });
61
    router.replace('/(tabs)/actions');
62
  };
63

64
  return (
65
    <KeyboardAvoidingView behavior="height" style={styles.keyboardView}>
66
      <ScrollView scrollEventThrottle={16}>
67
        <View style={styles.container}>
68
          <View style={styles.header}>
69
            <Text style={styles.headerTitle}>Novo medicamento</Text>
70
            <Text style={styles.headerSubtitle}>
71
              Informe os detalhes do medicamento
72
            </Text>
73
          </View>
74

75
          <Section>
76
            <SectionHeader title="Detalhes" />
77
            <Card style={{ padding: Spacing.cardGap }}>
78
              <Input
79
                label="Nome"
80
                value={medicineName}
81
                onChangeText={setMedicineName}
82
                placeholder="Ex: Fluoxetina"
83
                variant="darkGhost"
84
              />
85
              <Input
86
                label="Dosagem"
87
                value={medicineDosage}
88
                onChangeText={setMedicineDosage}
89
                placeholder="Ex: 20mg"
90
                variant="darkGhost"
91
              />
92
            </Card>
93
          </Section>
94

95
          <Section>
96
            <SectionHeader title="Frequência" />
97
            <View style={styles.periodicityRow}>
98
              {PERIODICITY_OPTIONS.map((opt) => (
99
                <TouchableOpacity
100
                  key={opt.value}
101
                  style={[
102
                    styles.periodicityChip,
103
                    medicinePeriodicity === opt.value && styles.periodicityChipActive,
104
                  ]}
105
                  onPress={() => {
106
                    setMedicinePeriodicity(opt.value);
107
                    const count = getTimePickerCount(opt.value);
108
                    setScheduledTimes(prev =>
109
                      count === 0 ? [] :
110
                      count > prev.length ? [...prev, ...Array(count - prev.length).fill(new Date())] :
111
                      prev.slice(0, count)
112
                    );
113
                  }}
114
                  activeOpacity={0.7}
115
                >
116
                  <Text
117
                    style={[
118
                      styles.periodicityChipLabel,
119
                      medicinePeriodicity === opt.value && styles.periodicityChipLabelActive,
120
                    ]}
121
                  >
122
                    {opt.label}
123
                  </Text>
124
                </TouchableOpacity>
125
              ))}
126
            </View>
127
          </Section>
128

129
          {scheduledTimes.length > 0 && (
130
            <Section>
131
              <SectionHeader title={scheduledTimes.length === 1 ? 'Horário' : 'Horários'} />
132
              {scheduledTimes.map((t, i) => (
133
                <View style={{ marginTop: 10 }} key={i}>
134
                  <TimePicker
135
                    value={t}
136
                    onChange={(date) =>
137
                      setScheduledTimes(prev => prev.map((v, idx) => idx === i ? date : v))
138
                    }
139
                  />
140
                </View>
141
              ))}
142
            </Section>
143
          )}
144

145
          <Button
146
            title="Salvar"
147
            onPress={handleSave}
148
            loading={createRegimen.isPending}
149
            disabled={!medicineName || !medicineDosage}
150
          />
151
        </View>
152
      </ScrollView>
153
    </KeyboardAvoidingView>
154
  );
155
}
156

157
const styles = StyleSheet.create({
158
  keyboardView: {
159
    flex: 1,
160
  },
161
  container: {
162
    gap: 24,
163
    paddingHorizontal: Spacing.containerPadding,
164
    paddingVertical: Spacing.sectionGap,
165
    marginBottom: 50,
166
  },
167
  header: {
168
    gap: 8,
169
  },
170
  headerTitle: {
171
    ...Typography.headlineMd,
172
  },
173
  headerSubtitle: {
174
    ...Typography.bodyMd,
175
    color: Colors.light.textSecondary,
176
  },
177
  periodicityRow: {
178
    flexDirection: 'row',
179
    flexWrap: 'wrap',
180
    gap: 8,
181
  },
182
  periodicityChip: {
183
    paddingHorizontal: 16,
184
    paddingVertical: 10,
185
    borderRadius: BorderRadius.full,
186
    backgroundColor: '#fff',
187
    borderWidth: 1.5,
188
    borderColor: Colors.light.divider,
189
  },
190
  periodicityChipActive: {
191
    backgroundColor: Colors.light.tint + '1A',
192
    borderColor: Colors.light.tint,
193
  },
194
  periodicityChipLabel: {
195
    fontSize: 14,
196
    fontWeight: '500',
197
    color: Colors.light.text,
198
  },
199
  periodicityChipLabelActive: {
200
    fontWeight: '600',
201
    color: Colors.light.text,
202
  },
203
});