eletrotupi / tcc/ frontend/app/care-actions/medicine-new.tsxfa18535ea443601fc1f62853fabb636e0930bcb5
6.3 KB | 211 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 = count > 0
54
      ? scheduledTimes.slice(0, count)
55
          .map(d => `${d.getHours().toString().padStart(2,'0')}:${d.getMinutes().toString().padStart(2,'0')}`)
56
          .join(',')
57
      : undefined;
58

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

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

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

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

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

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

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