eletrotupi / tcc/ frontend/app/care-actions/medicine-new.tsxca6234de503f574e5e6cd3a52e58f2d5b6c253f2
6.3 KB | 209 lines Raw
1
import {
2
  View,
3
  Text,
4
  StyleSheet,
5
  KeyboardAvoidingView,
6
  ScrollView,
7
  TouchableOpacity,
8
} from "react-native";
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, Shadows } from "@/constants/theme";
17
import { TimePicker } from "@/components/ui/TimePicker";
18
import { useCreateCareAction } 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
    case 'WEEKLY':
38
    case 'BIWEEKLY':
39
    case 'MONTHLY': return 1;
40
  }
41
}
42

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

49
  const createCareAction = useCreateCareAction();
50

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

57
    await createCareAction.mutateAsync({
58
      type: 'MEDICINE',
59
      moment: new Date(),
60
      medicine: {
61
        name: medicineName,
62
        dosage: medicineDosage,
63
        periodicity: medicinePeriodicity,
64
        scheduledAt,
65
      },
66
    });
67
    router.replace('/(tabs)/actions');
68
  };
69

70
  return (
71
    <KeyboardAvoidingView behavior="height" style={styles.keyboardView}>
72
      <ScrollView scrollEventThrottle={16}>
73
        <View style={styles.container}>
74
          <View style={styles.header}>
75
            <Text style={styles.headerTitle}>Novo medicamento</Text>
76
            <Text style={styles.headerSubtitle}>
77
              Informe os detalhes do medicamento
78
            </Text>
79
          </View>
80

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

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

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

151
          <Button
152
            title="Salvar"
153
            onPress={handleSave}
154
            loading={createCareAction.isPending}
155
            disabled={!medicineName || !medicineDosage}
156
          />
157
        </View>
158
      </ScrollView>
159
    </KeyboardAvoidingView>
160
  );
161
}
162

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