eletrotupi / tcc/ frontend/app/care-actions/appointment.tsxfa18535ea443601fc1f62853fabb636e0930bcb5
5.2 KB | 171 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 { TextArea } from "@/components/ui/Input";
14
import { Button } from "@/components/ui/Button";
15
import { Section, SectionHeader } from "@/components/ui/Sections";
16
import { CategoryChips, CategoryOption } from "@/components/ui/CategoryChips";
17
import { Spacing, Typography, Colors, BorderRadius, Shadows } from "@/constants/theme";
18
import { Ionicons } from "@expo/vector-icons";
19
import { useCreateCareAction } from "@/hooks";
20
import { AppointmentType } from "@/lib/api";
21

22
const APPOINTMENT_TYPES: CategoryOption<AppointmentType>[] = [
23
  { label: 'Analista', value: 'ANALYST', icon: <Ionicons name="person-outline" size={16} color={Colors.light.tint} /> },
24
  { label: 'Psiquiatra', value: 'PSYCHIATRIST', icon: <Ionicons name="medical-outline" size={16} color={Colors.light.tint} /> },
25
  { label: 'Clínico', value: 'GP', icon: <Ionicons name="fitness-outline" size={16} color={Colors.light.tint} /> },
26
  { label: 'Nutricionista', value: 'NUTRITIONIST', icon: <Ionicons name="nutrition-outline" size={16} color={Colors.light.tint} /> },
27
  { label: 'Outro', value: 'OTHER', icon: <Ionicons name="help-outline" size={16} color={Colors.light.tint} /> },
28
];
29

30
const DURATIONS = [30, 45, 50, 60];
31

32
export default function AppointmentCareAction() {
33
  const [appointmentType, setAppointmentType] = useState<AppointmentType>('ANALYST');
34
  const [appointmentDuration, setAppointmentDuration] = useState<number>(50);
35
  const [appointmentNote, setAppointmentNote] = useState('');
36

37
  const createCareAction = useCreateCareAction();
38

39
  const handleSave = async () => {
40
    await createCareAction.mutateAsync({
41
      type: 'APPOINTMENT',
42
      moment: new Date(),
43
      appointment: {
44
        type: appointmentType,
45
        duration: appointmentDuration,
46
        note: appointmentNote || undefined,
47
      },
48
    });
49
    router.replace('/care-actions/post-appointment');
50
  };
51

52
  return (
53
    <KeyboardAvoidingView behavior="height" style={styles.keyboardView}>
54
      <ScrollView scrollEventThrottle={16}>
55
        <View style={styles.container}>
56
          <View style={styles.header}>
57
            <Text style={styles.headerTitle}>Registrar consulta</Text>
58
            <Text style={styles.headerSubtitle}>
59
              Informe os detalhes da consulta ou sessão
60
            </Text>
61
          </View>
62

63
          <Section>
64
            <SectionHeader title="Tipo de consulta" />
65
            <CategoryChips
66
              options={APPOINTMENT_TYPES}
67
              active={appointmentType}
68
              onChange={setAppointmentType}
69
            />
70
          </Section>
71

72
          <Section>
73
            <SectionHeader title="Duração (min)" />
74
            <View style={styles.durationRow}>
75
              {DURATIONS.map((d) => (
76
                <TouchableOpacity
77
                  key={d}
78
                  style={[
79
                    styles.durationChip,
80
                    appointmentDuration === d && styles.durationChipActive,
81
                  ]}
82
                  onPress={() => setAppointmentDuration(d)}
83
                  activeOpacity={0.7}
84
                >
85
                  <Text
86
                    style={[
87
                      styles.durationLabel,
88
                      appointmentDuration === d && styles.durationLabelActive,
89
                    ]}
90
                  >
91
                    {d}
92
                  </Text>
93
                </TouchableOpacity>
94
              ))}
95
            </View>
96
          </Section>
97

98
          <Section>
99
            <SectionHeader title="Notas (opcional)" />
100
            <Card style={{ padding: Spacing.cardGap }}>
101
              <TextArea
102
                label="Como foi a consulta?"
103
                variant="darkGhost"
104
                value={appointmentNote}
105
                onChangeText={setAppointmentNote}
106
                minRows={4}
107
                placeholder="Descreva brevemente..."
108
              />
109
            </Card>
110
          </Section>
111

112
          <Button
113
            title="Salvar"
114
            onPress={handleSave}
115
            loading={createCareAction.isPending}
116
            style={{ ...Shadows.lg }}
117
          />
118
        </View>
119
      </ScrollView>
120
    </KeyboardAvoidingView>
121
  );
122
}
123

124
const styles = StyleSheet.create({
125
  keyboardView: {
126
    flex: 1,
127
  },
128
  container: {
129
    gap: 24,
130
    paddingHorizontal: Spacing.containerPadding,
131
    paddingVertical: Spacing.sectionGap,
132
    marginBottom: 50,
133
  },
134
  header: {
135
    gap: 8,
136
  },
137
  headerTitle: {
138
    ...Typography.headlineMd,
139
  },
140
  headerSubtitle: {
141
    ...Typography.bodyMd,
142
    color: Colors.light.textSecondary,
143
  },
144
  durationRow: {
145
    flexDirection: 'row',
146
    gap: 10,
147
    flexWrap: 'wrap',
148
  },
149
  durationChip: {
150
    paddingHorizontal: 20,
151
    paddingVertical: 12,
152
    borderRadius: BorderRadius.full,
153
    backgroundColor: '#fff',
154
    borderWidth: 1.5,
155
    borderColor: Colors.light.divider,
156
    minWidth: 64,
157
    alignItems: 'center',
158
  },
159
  durationChipActive: {
160
    backgroundColor: Colors.light.tint + '1A',
161
    borderColor: Colors.light.tint,
162
  },
163
  durationLabel: {
164
    fontSize: 16,
165
    fontWeight: '600',
166
    color: Colors.light.text,
167
  },
168
  durationLabelActive: {
169
    color: Colors.light.text,
170
  },
171
});