eletrotupi / tcc/ commit / 2e426df

frontend: initialize the edit forms from the loaded record

Pedro Lucas Porcellis porcellis@eletrotupi.com · 12 days ago 2e426df100e36abc7649699899f84bf7ee3b906b Browse files
Parents 6b0e21c
Changed files
3
Additions
+70
Deletions
-67
frontend/app/medicine-regimens/[id].tsx
1 1
import {
2 2
  View,
3 3
  StyleSheet,
4 4
  KeyboardAvoidingView,
5 5
  ScrollView,
6 6
  TouchableOpacity,
7 7
  ActivityIndicator,
8 8
} from "react-native";
9 9
import { Text } from "@/components/ui/Text";
10 -
import { useEffect, useState } from "react";
10 +
import { useState } from "react";
11 11
import { router, useLocalSearchParams } from "expo-router";
12 12
import { Card } from "@/components/ui/Cards";
13 13
import { Input } from "@/components/ui/Input";
14 14
import { Button } from "@/components/ui/Button";
15 15
import { Section, SectionHeader } from "@/components/ui/Sections";
16 16
import { Spacing, Typography, Colors, BorderRadius } from "@/constants/theme";
17 17
import { TimePicker } from "@/components/ui/TimePicker";
18 18
import { useMedicineRegimen, useUpdateMedicineRegimen } from "@/hooks";
19 -
import { MedicinePeriodicity } from "@/lib/api";
19 +
import type { MedicinePeriodicity, MedicineRegimen } from "@/lib/api";
20 20

21 21
const PERIODICITY_OPTIONS: { label: string; value: MedicinePeriodicity }[] = [
22 22
  { label: "Uma vez", value: "ONCE" },
23 23
  { label: "Diário", value: "DAILY" },
24 24
  { label: "2x ao dia", value: "TWICE_DAILY" },
48 48
}
49 49

50 50
export default function MedicineRegimenEdit() {
51 51
  const { id } = useLocalSearchParams<{ id: string }>();
52 52
  const { data, isLoading } = useMedicineRegimen(id);
53 +

54 +
  if (isLoading) {
55 +
    return (
56 +
      <View style={styles.center}>
57 +
        <ActivityIndicator color={Colors.light.tint} />
58 +
      </View>
59 +
    );
60 +
  }
61 +

62 +
  if (!data?.regimen) {
63 +
    return null;
64 +
  }
65 +

66 +
  return <MedicineRegimenForm id={id} regimen={data.regimen} />;
67 +
}
68 +

69 +
function MedicineRegimenForm({ id, regimen }: { id: string; regimen: MedicineRegimen }) {
53 70
  const updateRegimen = useUpdateMedicineRegimen();
54 71

55 -
  const [name, setName] = useState("");
56 -
  const [dosage, setDosage] = useState("");
57 -
  const [periodicity, setPeriodicity] = useState<MedicinePeriodicity>("DAILY");
58 -
  const [scheduledTimes, setScheduledTimes] = useState<Date[]>([]);
59 -
  const [initialized, setInitialized] = useState(false);
60 -

61 -
  useEffect(() => {
62 -
    if (data?.regimen && !initialized) {
63 -
      const r = data.regimen;
64 -
      setName(r.name);
65 -
      setDosage(r.dosage);
66 -
      setPeriodicity(r.periodicity as MedicinePeriodicity);
67 -
      setScheduledTimes(timesToDates(r.scheduledAt));
68 -
      setInitialized(true);
69 -
    }
70 -
  }, [data, initialized]);
72 +
  const [name, setName] = useState(regimen.name);
73 +
  const [dosage, setDosage] = useState(regimen.dosage);
74 +
  const [periodicity, setPeriodicity] = useState<MedicinePeriodicity>(regimen.periodicity);
75 +
  const [scheduledTimes, setScheduledTimes] = useState<Date[]>(
76 +
    timesToDates(regimen.scheduledAt),
77 +
  );
71 78

72 79
  const handleSave = async () => {
73 80
    const count = getTimePickerCount(periodicity);
74 81
    const scheduledAt = scheduledTimes.slice(0, count).map(
75 82
      (d) =>
80 87
      id,
81 88
      payload: { name, dosage, periodicity, scheduledAt },
82 89
    });
83 90
    router.back();
84 91
  };
85 -

86 -
  if (isLoading || !initialized) {
87 -
    return (
88 -
      <View style={styles.center}>
89 -
        <ActivityIndicator color={Colors.light.tint} />
90 -
      </View>
91 -
    );
92 -
  }
93 92

94 93
  return (
95 94
    <KeyboardAvoidingView behavior="height" style={styles.keyboardView}>
96 95
      <ScrollView scrollEventThrottle={16}>
97 96
        <View style={styles.container}>
230 229
  periodicityChipLabelActive: {
231 230
    fontWeight: "600",
232 231
    color: Colors.light.text,
233 232
  },
234 233
});
frontend/app/sleep/edit/[id].tsx
1 1
import {
2 2
  View,
3 3
  StyleSheet,
4 4
  KeyboardAvoidingView,
5 5
  ScrollView,
6 +
  ActivityIndicator,
6 7
} from "react-native";
7 8
import { Text } from "@/components/ui/Text";
8 -
import { useState, useEffect } from "react";
9 +
import { useState } from "react";
9 10
import { router, useLocalSearchParams, Stack } from "expo-router";
10 11

11 12
import { Card } from "@/components/ui/Cards";
12 13
import { TextArea } from "@/components/ui/Input";
13 14
import { Button } from "@/components/ui/Button";
15 16
import { Ionicons } from "@expo/vector-icons";
16 17
import { DatePickerField } from "@/components/ui/DatePickerField";
17 18
import { ScaleSlider } from "@/components/ui/ScaleSlider";
18 19
import { useSleepRecord, useUpdateSleepRecord } from "@/hooks";
19 20
import { parseDateOnly } from "@/lib/utils/time";
20 -
import { ActivityIndicator, View as ActivityView } from "react-native";
21 +
import type { SleepRecord } from "@/lib/api";
21 22

22 23
export default function EditSleepRecord() {
23 24
  const { id } = useLocalSearchParams<{ id: string }>();
24 25
  const { data: sleepRecord, isLoading } = useSleepRecord(id);
25 -
  const updateSleepRecord = useUpdateSleepRecord();
26 26

27 -
  const [date, setDate] = useState(new Date());
28 -
  const [annotations, setAnnotations] = useState("");
29 -
  const [average, setAverage] = useState(7.5);
27 +
  if (isLoading) {
28 +
    return (
29 +
      <View style={styles.centered}>
30 +
        <ActivityIndicator size="large" color={Colors.light.tint} />
31 +
      </View>
32 +
    );
33 +
  }
30 34

31 -
  useEffect(() => {
32 -
    if (sleepRecord) {
33 -
      setDate(parseDateOnly(sleepRecord.date));
34 -
      setAnnotations(sleepRecord.annotations || "");
35 -
      setAverage(sleepRecord.average);
36 -
    }
37 -
  }, [sleepRecord]);
35 +
  if (!sleepRecord) {
36 +
    return null;
37 +
  }
38 +

39 +
  return <EditSleepForm id={id} sleepRecord={sleepRecord} />;
40 +
}
41 +

42 +
function EditSleepForm({ id, sleepRecord }: { id: string; sleepRecord: SleepRecord }) {
43 +
  const updateSleepRecord = useUpdateSleepRecord();
44 +

45 +
  const [date, setDate] = useState(parseDateOnly(sleepRecord.date));
46 +
  const [annotations, setAnnotations] = useState(sleepRecord.annotations || "");
47 +
  const [average, setAverage] = useState(sleepRecord.average);
38 48

39 49
  const formatValue = (value: number): string => {
40 50
    return String(value).replaceAll(".", ",");
41 51
  };
42 52

48 58
    };
49 59

50 60
    await updateSleepRecord.mutateAsync({ id: String(id), payload: data });
51 61
    router.back();
52 62
  };
53 -

54 -
  if (isLoading) {
55 -
    return (
56 -
      <ActivityView style={styles.centered}>
57 -
        <ActivityIndicator size="large" color={Colors.light.tint} />
58 -
      </ActivityView>
59 -
    );
60 -
  }
61 63

62 64
  return (
63 65
    <KeyboardAvoidingView behavior="height" style={styles.keyboardView}>
64 66
      <Stack.Screen options={{ title: "Editar Registro" }} />
65 67
      <ScrollView scrollEventThrottle={16}>
172 174
    flex: 1,
173 175
    justifyContent: "center",
174 176
    alignItems: "center",
175 177
  },
176 178
});
frontend/app/triggers/edit/[id].tsx
1 1
import {
2 2
  View,
3 3
  StyleSheet,
4 4
  KeyboardAvoidingView,
5 5
  ScrollView,
6 6
  ActivityIndicator,
7 7
} from "react-native";
8 8
import { Text } from "@/components/ui/Text";
9 -
import { useState, useEffect } from "react";
9 +
import { useState } from "react";
10 10
import { router, useLocalSearchParams, Stack } from "expo-router";
11 11

12 12
import { Card } from "@/components/ui/Cards";
13 13
import { TextArea } from "@/components/ui/Input";
14 14
import { Button } from "@/components/ui/Button";
18 18
import { useUpdateTrigger, useTrigger } from "@/hooks";
19 19
import { CategoryChips, CategoryOption } from "@/components/ui/CategoryChips";
20 20
import { TriggerCategory } from "@/constants/triggers";
21 21
import { TRIGGER_CATEGORY_DEFINITIONS } from "@/constants/trigger-categories";
22 22
import { TimePicker } from "@/components/ui/TimePicker";
23 +
import type { Trigger } from "@/lib/api";
23 24

24 25
const TRIGGER_CATEGORIES: CategoryOption<TriggerCategory>[] =
25 26
  TRIGGER_CATEGORY_DEFINITIONS.map((d) => ({
26 27
    label: d.label,
27 28
    value: d.id,
29 30
  }));
30 31

31 32
export default function EditTrigger() {
32 33
  const { id } = useLocalSearchParams<{ id: string }>();
33 34
  const { data: trigger, isLoading } = useTrigger(id);
34 -
  const updateTrigger = useUpdateTrigger();
35 35

36 -
  const [moment, setMoment] = useState(new Date());
37 -
  const [comment, setComment] = useState("");
38 -
  const [category, setCategory] = useState("WORK");
36 +
  if (isLoading) {
37 +
    return (
38 +
      <View style={styles.centered}>
39 +
        <ActivityIndicator size="large" color={Colors.light.tint} />
40 +
      </View>
41 +
    );
42 +
  }
39 43

40 -
  useEffect(() => {
41 -
    if (trigger) {
42 -
      setMoment(new Date(trigger.moment));
43 -
      setComment(trigger.comment || "");
44 -
      setCategory(trigger.category);
45 -
    }
46 -
  }, [trigger]);
44 +
  if (!trigger) {
45 +
    return null;
46 +
  }
47 +

48 +
  return <EditTriggerForm id={id} trigger={trigger} />;
49 +
}
50 +

51 +
function EditTriggerForm({ id, trigger }: { id: string; trigger: Trigger }) {
52 +
  const updateTrigger = useUpdateTrigger();
53 +

54 +
  const [moment, setMoment] = useState(new Date(trigger.moment));
55 +
  const [comment, setComment] = useState(trigger.comment || "");
56 +
  const [category, setCategory] = useState(trigger.category);
47 57

48 58
  const save = async () => {
49 59
    const data = {
50 60
      moment,
51 61
      comment,
53 63
    };
54 64

55 65
    await updateTrigger.mutateAsync({ id: String(id), payload: data });
56 66
    router.back();
57 67
  };
58 -

59 -
  if (isLoading) {
60 -
    return (
61 -
      <View style={styles.centered}>
62 -
        <ActivityIndicator size="large" color={Colors.light.tint} />
63 -
      </View>
64 -
    );
65 -
  }
66 68

67 69
  return (
68 70
    <KeyboardAvoidingView behavior="height" style={styles.keyboardView}>
69 71
      <Stack.Screen options={{ title: "Editar Registro" }} />
70 72
      <ScrollView scrollEventThrottle={16}>
175 177
    flex: 1,
176 178
    justifyContent: "center",
177 179
    alignItems: "center",
178 180
  },
179 181
});