import { DateTimePickerAndroid } from "@react-native-community/datetimepicker"; import { NavigationProp, RouteProp, useFocusEffect, useNavigation, useRoute, } from "@react-navigation/native"; import { format } from "date-fns"; import { useCallback, useRef, useState } from "react"; import { DeviceEventEmitter, NativeModules, TextInput, View, } from "react-native"; import DocumentPicker from "react-native-document-picker"; import { Button, Card, IconButton, TouchableRipple } from "react-native-paper"; import AppInput from "./AppInput"; import ConfirmDialog from "./ConfirmDialog"; import { GYM_SET_CREATED, GYM_SET_UPDATED, MARGIN, PADDING } from "./constants"; import { getNow, setRepo, settingsRepo } from "./db"; import GymSet from "./gym-set"; import { HomePageParams } from "./home-page-params"; import Settings from "./settings"; import StackHeader from "./StackHeader"; import { toast } from "./toast"; import { fixNumeric } from "./fix-numeric"; export default function EditSet() { const { params } = useRoute>(); const { set } = params; const { navigate } = useNavigation>(); const [settings, setSettings] = useState({} as Settings); const [name, setName] = useState(set.name); const [reps, setReps] = useState(set.reps?.toString()); const [weight, setWeight] = useState(set.weight?.toString()); const [newImage, setNewImage] = useState(set.image); const [unit, setUnit] = useState(set.unit); const [created, setCreated] = useState( set.created ? new Date(set.created) : new Date() ); const [createdDirty, setCreatedDirty] = useState(false); const [showRemove, setShowRemove] = useState(false); const [removeImage, setRemoveImage] = useState(false); const weightRef = useRef(null); const repsRef = useRef(null); const unitRef = useRef(null); const [selection, setSelection] = useState({ start: 0, end: set.reps?.toString().length, }); useFocusEffect( useCallback(() => { settingsRepo.findOne({ where: {} }).then(setSettings); }, []) ); const startTimer = useCallback( async (value: string) => { if (!settings.alarm) return; const first = await setRepo.findOne({ where: { name: value } }); const milliseconds = (first?.minutes ?? 3) * 60 * 1000 + (first?.seconds ?? 0) * 1000; if (milliseconds) NativeModules.AlarmModule.timer(milliseconds); }, [settings] ); const added = async (value: GymSet) => { DeviceEventEmitter.emit(GYM_SET_CREATED); startTimer(value.name); console.log(`${EditSet.name}.add`, { set: value }); if (!settings.notify) return; if ( value.weight > set.weight || (value.reps > set.reps && value.weight === set.weight) ) { toast("Great work King! That's a new record."); } navigate("Sets", { reset: value.id }); }; const handleSubmit = async () => { if (!name) return; const newSet: Partial = { id: set.id, name, reps: Number(reps), weight: Number(weight), unit, minutes: Number(set.minutes ?? 3), seconds: Number(set.seconds ?? 30), sets: set.sets ?? 3, hidden: false, }; newSet.image = newImage; if (!newImage && !removeImage) { newSet.image = await setRepo .findOne({ where: { name } }) .then((s) => s?.image); } if (createdDirty) newSet.created = created.toISOString(); if (typeof set.id !== "number") newSet.created = await getNow(); const saved = await setRepo.save(newSet); if (typeof set.id !== "number") return added(saved); DeviceEventEmitter.emit(GYM_SET_UPDATED); if (createdDirty) navigate("Sets", { reset: saved.id }); else navigate("Sets", { refresh: saved.id }); }; const changeImage = useCallback(async () => { const { fileCopyUri } = await DocumentPicker.pickSingle({ type: DocumentPicker.types.images, copyTo: "documentDirectory", }); if (fileCopyUri) setNewImage(fileCopyUri); }, []); const handleRemove = useCallback(async () => { setNewImage(""); setRemoveImage(true); setShowRemove(false); }, []); const pickDate = useCallback(() => { DateTimePickerAndroid.open({ value: created, onChange: (_, date) => { if (date === created) return; setCreated(date); setCreatedDirty(true); DateTimePickerAndroid.open({ value: date, onChange: (__, time) => setCreated(time), mode: "time", }); }, mode: "date", }); }, [created]); return ( <> repsRef.current?.focus()} /> { const fixed = fixNumeric(newReps); setReps(fixed); if (fixed.length !== newReps.length) toast("Reps must be a number"); }} onSubmitEditing={() => weightRef.current?.focus()} selection={selection} onSelectionChange={(e) => setSelection(e.nativeEvent.selection)} innerRef={repsRef} /> setReps((Number(reps) + 1).toString())} /> setReps((Number(reps) - 1).toString())} /> { const fixed = fixNumeric(newWeight); setWeight(fixed); if (fixed.length !== newWeight.length) toast("Weight must be a number"); }} onSubmitEditing={handleSubmit} innerRef={weightRef} /> setWeight((Number(weight) + 2.5).toString())} /> setWeight((Number(weight) - 2.5).toString())} /> {settings.showUnit && ( )} {settings.showDate && ( )} {settings.images && newImage && ( setShowRemove(true)} > )} {settings.images && !newImage && ( )} Are you sure you want to remove the image? ); }