Add ability to edit/delete multiple sets/plans
This commit is contained in:
parent
c3b14e901d
commit
2e347deb53
|
@ -6,13 +6,20 @@ export default function ConfirmDialog({
|
||||||
onOk,
|
onOk,
|
||||||
show,
|
show,
|
||||||
setShow,
|
setShow,
|
||||||
|
onCancel,
|
||||||
}: {
|
}: {
|
||||||
title: string
|
title: string
|
||||||
children: JSX.Element | JSX.Element[] | string
|
children: JSX.Element | JSX.Element[] | string
|
||||||
onOk: () => void
|
onOk: () => void
|
||||||
show: boolean
|
show: boolean
|
||||||
setShow: (show: boolean) => void
|
setShow: (show: boolean) => void
|
||||||
|
onCancel?: () => void
|
||||||
}) {
|
}) {
|
||||||
|
const cancel = () => {
|
||||||
|
setShow(false)
|
||||||
|
onCancel && onCancel()
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Portal>
|
<Portal>
|
||||||
<Dialog visible={show} onDismiss={() => setShow(false)}>
|
<Dialog visible={show} onDismiss={() => setShow(false)}>
|
||||||
|
@ -22,7 +29,7 @@ export default function ConfirmDialog({
|
||||||
</Dialog.Content>
|
</Dialog.Content>
|
||||||
<Dialog.Actions>
|
<Dialog.Actions>
|
||||||
<Button onPress={onOk}>OK</Button>
|
<Button onPress={onOk}>OK</Button>
|
||||||
<Button onPress={() => setShow(false)}>Cancel</Button>
|
<Button onPress={cancel}>Cancel</Button>
|
||||||
</Dialog.Actions>
|
</Dialog.Actions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</Portal>
|
</Portal>
|
||||||
|
|
|
@ -5,7 +5,13 @@ import {DrawerParamList} from './drawer-param-list'
|
||||||
import DrawerMenu from './DrawerMenu'
|
import DrawerMenu from './DrawerMenu'
|
||||||
import useDark from './use-dark'
|
import useDark from './use-dark'
|
||||||
|
|
||||||
export default function DrawerHeader({name}: {name: keyof DrawerParamList}) {
|
export default function DrawerHeader({
|
||||||
|
name,
|
||||||
|
ids,
|
||||||
|
}: {
|
||||||
|
name: keyof DrawerParamList
|
||||||
|
ids: number[]
|
||||||
|
}) {
|
||||||
const navigation = useNavigation<DrawerNavigationProp<DrawerParamList>>()
|
const navigation = useNavigation<DrawerNavigationProp<DrawerParamList>>()
|
||||||
const dark = useDark()
|
const dark = useDark()
|
||||||
|
|
||||||
|
@ -17,7 +23,7 @@ export default function DrawerHeader({name}: {name: keyof DrawerParamList}) {
|
||||||
onPress={navigation.openDrawer}
|
onPress={navigation.openDrawer}
|
||||||
/>
|
/>
|
||||||
<Appbar.Content title={name} />
|
<Appbar.Content title={name} />
|
||||||
<DrawerMenu name={name} />
|
<DrawerMenu name={name} ids={ids} />
|
||||||
</Appbar.Header>
|
</Appbar.Header>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,23 +4,34 @@ import {IconButton, Menu} from 'react-native-paper'
|
||||||
import ConfirmDialog from './ConfirmDialog'
|
import ConfirmDialog from './ConfirmDialog'
|
||||||
import {planRepo, setRepo} from './db'
|
import {planRepo, setRepo} from './db'
|
||||||
import {DrawerParamList} from './drawer-param-list'
|
import {DrawerParamList} from './drawer-param-list'
|
||||||
import {toast} from './toast'
|
import {HomePageParams} from './home-page-params'
|
||||||
import useDark from './use-dark'
|
import useDark from './use-dark'
|
||||||
|
|
||||||
export default function DrawerMenu({name}: {name: keyof DrawerParamList}) {
|
export default function DrawerMenu({
|
||||||
|
name,
|
||||||
|
ids,
|
||||||
|
}: {
|
||||||
|
name: keyof DrawerParamList
|
||||||
|
ids: number[]
|
||||||
|
}) {
|
||||||
const [showMenu, setShowMenu] = useState(false)
|
const [showMenu, setShowMenu] = useState(false)
|
||||||
const [showRemove, setShowRemove] = useState(false)
|
const [showRemove, setShowRemove] = useState(false)
|
||||||
const {reset} = useNavigation<NavigationProp<DrawerParamList>>()
|
const {reset} = useNavigation<NavigationProp<DrawerParamList>>()
|
||||||
|
const {navigate} = useNavigation<NavigationProp<HomePageParams>>()
|
||||||
const dark = useDark()
|
const dark = useDark()
|
||||||
|
|
||||||
const remove = useCallback(async () => {
|
const remove = useCallback(async () => {
|
||||||
setShowMenu(false)
|
setShowMenu(false)
|
||||||
setShowRemove(false)
|
setShowRemove(false)
|
||||||
if (name === 'Home') await setRepo.delete({})
|
if (name === 'Home') await setRepo.delete(ids.length > 0 ? ids : {})
|
||||||
else if (name === 'Plans') await planRepo.delete({})
|
else if (name === 'Plans') await planRepo.delete(ids.length > 0 ? ids : {})
|
||||||
toast('All data has been deleted.')
|
|
||||||
reset({index: 0, routes: [{name}]})
|
reset({index: 0, routes: [{name}]})
|
||||||
}, [reset, name])
|
}, [reset, name, ids])
|
||||||
|
|
||||||
|
const edit = useCallback(() => {
|
||||||
|
navigate('EditSets', {ids})
|
||||||
|
setShowMenu(false)
|
||||||
|
}, [ids, navigate])
|
||||||
|
|
||||||
if (name === 'Home' || name === 'Plans')
|
if (name === 'Home' || name === 'Plans')
|
||||||
return (
|
return (
|
||||||
|
@ -39,12 +50,22 @@ export default function DrawerMenu({name}: {name: keyof DrawerParamList}) {
|
||||||
onPress={() => setShowRemove(true)}
|
onPress={() => setShowRemove(true)}
|
||||||
title="Delete"
|
title="Delete"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{ids.length > 0 && name === 'Home' && (
|
||||||
|
<Menu.Item icon="edit" title="Edit" onPress={edit} />
|
||||||
|
)}
|
||||||
|
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
title="Delete all data"
|
title="Delete all data"
|
||||||
show={showRemove}
|
show={showRemove}
|
||||||
setShow={setShowRemove}
|
setShow={setShowRemove}
|
||||||
onOk={remove}>
|
onOk={remove}
|
||||||
This irreversibly deletes all data from the app. Are you sure?
|
onCancel={() => setShowMenu(false)}>
|
||||||
|
{ids.length === 0 ? (
|
||||||
|
<>This irreversibly deletes all data from the app. Are you sure?</>
|
||||||
|
) : (
|
||||||
|
<>This will delete {ids.length} records. Are you sure?</>
|
||||||
|
)}
|
||||||
</ConfirmDialog>
|
</ConfirmDialog>
|
||||||
</Menu>
|
</Menu>
|
||||||
)
|
)
|
||||||
|
|
151
EditSets.tsx
Normal file
151
EditSets.tsx
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
import {
|
||||||
|
RouteProp,
|
||||||
|
useFocusEffect,
|
||||||
|
useNavigation,
|
||||||
|
useRoute,
|
||||||
|
} from '@react-navigation/native'
|
||||||
|
import {useCallback, useRef, useState} from 'react'
|
||||||
|
import {TextInput, View} from 'react-native'
|
||||||
|
import DocumentPicker from 'react-native-document-picker'
|
||||||
|
import {Button, Card, TouchableRipple} from 'react-native-paper'
|
||||||
|
import ConfirmDialog from './ConfirmDialog'
|
||||||
|
import {MARGIN, PADDING} from './constants'
|
||||||
|
import {setRepo, settingsRepo} from './db'
|
||||||
|
import GymSet from './gym-set'
|
||||||
|
import {HomePageParams} from './home-page-params'
|
||||||
|
import MassiveInput from './MassiveInput'
|
||||||
|
import Settings from './settings'
|
||||||
|
import StackHeader from './StackHeader'
|
||||||
|
|
||||||
|
export default function EditSets() {
|
||||||
|
const {params} = useRoute<RouteProp<HomePageParams, 'EditSets'>>()
|
||||||
|
const {ids} = params
|
||||||
|
const navigation = useNavigation()
|
||||||
|
const [settings, setSettings] = useState<Settings>({} as Settings)
|
||||||
|
const [name, setName] = useState('')
|
||||||
|
const [reps, setReps] = useState('')
|
||||||
|
const [weight, setWeight] = useState('')
|
||||||
|
const [newImage, setNewImage] = useState('')
|
||||||
|
const [unit, setUnit] = useState('')
|
||||||
|
const [showRemove, setShowRemove] = useState(false)
|
||||||
|
const weightRef = useRef<TextInput>(null)
|
||||||
|
const repsRef = useRef<TextInput>(null)
|
||||||
|
const unitRef = useRef<TextInput>(null)
|
||||||
|
|
||||||
|
const [selection, setSelection] = useState({
|
||||||
|
start: 0,
|
||||||
|
end: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
settingsRepo.findOne({where: {}}).then(setSettings)
|
||||||
|
}, []),
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
console.log(`${EditSets.name}.handleSubmit:`, {uri: newImage, name})
|
||||||
|
const update: Partial<GymSet> = {}
|
||||||
|
if (name) update.name = name
|
||||||
|
if (reps) update.reps = Number(reps)
|
||||||
|
if (weight) update.weight = Number(weight)
|
||||||
|
if (unit) update.unit = unit
|
||||||
|
if (newImage) update.image = newImage
|
||||||
|
await setRepo.update(ids, update)
|
||||||
|
navigation.goBack()
|
||||||
|
}
|
||||||
|
|
||||||
|
const changeImage = useCallback(async () => {
|
||||||
|
const {fileCopyUri} = await DocumentPicker.pickSingle({
|
||||||
|
type: DocumentPicker.types.images,
|
||||||
|
copyTo: 'documentDirectory',
|
||||||
|
})
|
||||||
|
if (fileCopyUri) setNewImage(fileCopyUri)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleRemove = useCallback(async () => {
|
||||||
|
setNewImage('')
|
||||||
|
setShowRemove(false)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<StackHeader title={`Edit ${ids.length} sets`} />
|
||||||
|
|
||||||
|
<View style={{padding: PADDING, flex: 1}}>
|
||||||
|
<MassiveInput
|
||||||
|
label="Name"
|
||||||
|
value={name}
|
||||||
|
onChangeText={setName}
|
||||||
|
autoCorrect={false}
|
||||||
|
autoFocus={!name}
|
||||||
|
onSubmitEditing={() => repsRef.current?.focus()}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MassiveInput
|
||||||
|
label="Reps"
|
||||||
|
keyboardType="numeric"
|
||||||
|
value={reps}
|
||||||
|
onChangeText={setReps}
|
||||||
|
onSubmitEditing={() => weightRef.current?.focus()}
|
||||||
|
selection={selection}
|
||||||
|
onSelectionChange={e => setSelection(e.nativeEvent.selection)}
|
||||||
|
autoFocus={!!name}
|
||||||
|
innerRef={repsRef}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MassiveInput
|
||||||
|
label="Weight"
|
||||||
|
keyboardType="numeric"
|
||||||
|
value={weight}
|
||||||
|
onChangeText={setWeight}
|
||||||
|
onSubmitEditing={handleSubmit}
|
||||||
|
innerRef={weightRef}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{settings.showUnit && (
|
||||||
|
<MassiveInput
|
||||||
|
autoCapitalize="none"
|
||||||
|
label="Unit"
|
||||||
|
value={unit}
|
||||||
|
onChangeText={setUnit}
|
||||||
|
innerRef={unitRef}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{settings.images && newImage && (
|
||||||
|
<TouchableRipple
|
||||||
|
style={{marginBottom: MARGIN}}
|
||||||
|
onPress={changeImage}
|
||||||
|
onLongPress={() => setShowRemove(true)}>
|
||||||
|
<Card.Cover source={{uri: newImage}} />
|
||||||
|
</TouchableRipple>
|
||||||
|
)}
|
||||||
|
<ConfirmDialog
|
||||||
|
title="Remove image"
|
||||||
|
onOk={handleRemove}
|
||||||
|
show={showRemove}
|
||||||
|
setShow={setShowRemove}>
|
||||||
|
Are you sure you want to remove the image?
|
||||||
|
</ConfirmDialog>
|
||||||
|
|
||||||
|
{settings.images && !newImage && (
|
||||||
|
<Button
|
||||||
|
style={{marginBottom: MARGIN}}
|
||||||
|
onPress={changeImage}
|
||||||
|
icon="add-photo-alternate">
|
||||||
|
Image
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
mode="contained"
|
||||||
|
icon="save"
|
||||||
|
style={{margin: MARGIN}}
|
||||||
|
onPress={handleSubmit}>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import {createStackNavigator} from '@react-navigation/stack'
|
import {createStackNavigator} from '@react-navigation/stack'
|
||||||
import EditSet from './EditSet'
|
import EditSet from './EditSet'
|
||||||
|
import EditSets from './EditSets'
|
||||||
import {HomePageParams} from './home-page-params'
|
import {HomePageParams} from './home-page-params'
|
||||||
import SetList from './SetList'
|
import SetList from './SetList'
|
||||||
|
|
||||||
|
@ -11,6 +12,7 @@ export default function HomePage() {
|
||||||
screenOptions={{headerShown: false, animationEnabled: false}}>
|
screenOptions={{headerShown: false, animationEnabled: false}}>
|
||||||
<Stack.Screen name="Sets" component={SetList} />
|
<Stack.Screen name="Sets" component={SetList} />
|
||||||
<Stack.Screen name="EditSet" component={EditSet} />
|
<Stack.Screen name="EditSet" component={EditSet} />
|
||||||
|
<Stack.Screen name="EditSets" component={EditSets} />
|
||||||
</Stack.Navigator>
|
</Stack.Navigator>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
67
PlanItem.tsx
67
PlanItem.tsx
|
@ -4,25 +4,26 @@ import {
|
||||||
useNavigation,
|
useNavigation,
|
||||||
} from '@react-navigation/native'
|
} from '@react-navigation/native'
|
||||||
import {useCallback, useMemo, useState} from 'react'
|
import {useCallback, useMemo, useState} from 'react'
|
||||||
import {GestureResponderEvent, Text} from 'react-native'
|
import {Text} from 'react-native'
|
||||||
import {Divider, List, Menu} from 'react-native-paper'
|
import {List} from 'react-native-paper'
|
||||||
import {getBestSet} from './best.service'
|
import {getBestSet} from './best.service'
|
||||||
import {planRepo} from './db'
|
|
||||||
import {defaultSet} from './gym-set'
|
import {defaultSet} from './gym-set'
|
||||||
import {Plan} from './plan'
|
import {Plan} from './plan'
|
||||||
import {PlanPageParams} from './plan-page-params'
|
import {PlanPageParams} from './plan-page-params'
|
||||||
import {DAYS} from './time'
|
import {DAYS} from './time'
|
||||||
|
import useDark from './use-dark'
|
||||||
|
|
||||||
export default function PlanItem({
|
export default function PlanItem({
|
||||||
item,
|
item,
|
||||||
onRemove,
|
setIds,
|
||||||
|
ids,
|
||||||
}: {
|
}: {
|
||||||
item: Plan
|
item: Plan
|
||||||
onRemove: () => void
|
ids: number[]
|
||||||
|
setIds: (value: number[]) => void
|
||||||
}) {
|
}) {
|
||||||
const [show, setShow] = useState(false)
|
|
||||||
const [anchor, setAnchor] = useState({x: 0, y: 0})
|
|
||||||
const [today, setToday] = useState<string>()
|
const [today, setToday] = useState<string>()
|
||||||
|
const dark = useDark()
|
||||||
const days = useMemo(() => item.days.split(','), [item.days])
|
const days = useMemo(() => item.days.split(','), [item.days])
|
||||||
const navigation = useNavigation<NavigationProp<PlanPageParams>>()
|
const navigation = useNavigation<NavigationProp<PlanPageParams>>()
|
||||||
|
|
||||||
|
@ -33,34 +34,22 @@ export default function PlanItem({
|
||||||
}, []),
|
}, []),
|
||||||
)
|
)
|
||||||
|
|
||||||
const remove = useCallback(async () => {
|
|
||||||
if (typeof item.id === 'number') await planRepo.delete(item.id)
|
|
||||||
setShow(false)
|
|
||||||
onRemove()
|
|
||||||
}, [setShow, item.id, onRemove])
|
|
||||||
|
|
||||||
const start = useCallback(async () => {
|
const start = useCallback(async () => {
|
||||||
console.log(`${PlanItem.name}.start:`, {item})
|
|
||||||
setShow(false)
|
|
||||||
const workout = item.workouts.split(',')[0]
|
const workout = item.workouts.split(',')[0]
|
||||||
let first = await getBestSet(workout)
|
let first = await getBestSet(workout)
|
||||||
if (!first) first = {...defaultSet, name: workout}
|
if (!first) first = {...defaultSet, name: workout}
|
||||||
delete first.id
|
delete first.id
|
||||||
navigation.navigate('StartPlan', {plan: item, first})
|
if (ids.length === 0)
|
||||||
}, [item, navigation])
|
return navigation.navigate('StartPlan', {plan: item, first})
|
||||||
|
const removing = ids.find(id => id === item.id)
|
||||||
|
if (removing) setIds(ids.filter(id => id !== item.id))
|
||||||
|
else setIds([...ids, item.id])
|
||||||
|
}, [ids, setIds, item, navigation])
|
||||||
|
|
||||||
const longPress = useCallback(
|
const longPress = useCallback(() => {
|
||||||
(e: GestureResponderEvent) => {
|
if (ids.length > 0) return
|
||||||
setAnchor({x: e.nativeEvent.pageX, y: e.nativeEvent.pageY})
|
setIds([item.id])
|
||||||
setShow(true)
|
}, [ids.length, item.id, setIds])
|
||||||
},
|
|
||||||
[setAnchor, setShow],
|
|
||||||
)
|
|
||||||
|
|
||||||
const edit = useCallback(() => {
|
|
||||||
setShow(false)
|
|
||||||
navigation.navigate('EditPlan', {plan: item})
|
|
||||||
}, [navigation, item])
|
|
||||||
|
|
||||||
const title = useMemo(
|
const title = useMemo(
|
||||||
() =>
|
() =>
|
||||||
|
@ -84,12 +73,11 @@ export default function PlanItem({
|
||||||
[item.workouts],
|
[item.workouts],
|
||||||
)
|
)
|
||||||
|
|
||||||
const copy = useCallback(() => {
|
const backgroundColor = useMemo(() => {
|
||||||
const plan: Plan = {...item}
|
if (!ids.includes(item.id)) return
|
||||||
delete plan.id
|
if (dark) return '#c2c2c2'
|
||||||
setShow(false)
|
return '#c2c2c2'
|
||||||
navigation.navigate('EditPlan', {plan})
|
}, [dark, ids, item.id])
|
||||||
}, [navigation, item])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<List.Item
|
<List.Item
|
||||||
|
@ -97,14 +85,7 @@ export default function PlanItem({
|
||||||
title={title}
|
title={title}
|
||||||
description={description}
|
description={description}
|
||||||
onLongPress={longPress}
|
onLongPress={longPress}
|
||||||
right={() => (
|
style={{backgroundColor}}
|
||||||
<Menu anchor={anchor} visible={show} onDismiss={() => setShow(false)}>
|
|
||||||
<Menu.Item icon="edit" onPress={edit} title="Edit" />
|
|
||||||
<Menu.Item icon="content-copy" onPress={copy} title="Copy" />
|
|
||||||
<Divider />
|
|
||||||
<Menu.Item icon="delete" onPress={remove} title="Delete" />
|
|
||||||
</Menu>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import PlanItem from './PlanItem'
|
||||||
export default function PlanList() {
|
export default function PlanList() {
|
||||||
const [term, setTerm] = useState('')
|
const [term, setTerm] = useState('')
|
||||||
const [plans, setPlans] = useState<Plan[]>()
|
const [plans, setPlans] = useState<Plan[]>()
|
||||||
|
const [ids, setIds] = useState<number[]>([])
|
||||||
const navigation = useNavigation<NavigationProp<PlanPageParams>>()
|
const navigation = useNavigation<NavigationProp<PlanPageParams>>()
|
||||||
|
|
||||||
const refresh = useCallback(async (value: string) => {
|
const refresh = useCallback(async (value: string) => {
|
||||||
|
@ -43,9 +44,9 @@ export default function PlanList() {
|
||||||
|
|
||||||
const renderItem = useCallback(
|
const renderItem = useCallback(
|
||||||
({item}: {item: Plan}) => (
|
({item}: {item: Plan}) => (
|
||||||
<PlanItem item={item} key={item.id} onRemove={() => refresh(term)} />
|
<PlanItem ids={ids} setIds={setIds} item={item} key={item.id} />
|
||||||
),
|
),
|
||||||
[refresh, term],
|
[ids],
|
||||||
)
|
)
|
||||||
|
|
||||||
const onAdd = () =>
|
const onAdd = () =>
|
||||||
|
@ -53,7 +54,7 @@ export default function PlanList() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DrawerHeader name="Plans" />
|
<DrawerHeader name="Plans" ids={ids} />
|
||||||
<Page onAdd={onAdd} term={term} search={search}>
|
<Page onAdd={onAdd} term={term} search={search}>
|
||||||
{plans?.length === 0 ? (
|
{plans?.length === 0 ? (
|
||||||
<List.Item
|
<List.Item
|
||||||
|
|
61
SetItem.tsx
61
SetItem.tsx
|
@ -1,57 +1,54 @@
|
||||||
import {NavigationProp, useNavigation} from '@react-navigation/native'
|
import {NavigationProp, useNavigation} from '@react-navigation/native'
|
||||||
import {useCallback, useState} from 'react'
|
import {format} from 'date-fns'
|
||||||
import {GestureResponderEvent, Image} from 'react-native'
|
import {useCallback, useMemo} from 'react'
|
||||||
import {Divider, List, Menu, Text} from 'react-native-paper'
|
import {Image} from 'react-native'
|
||||||
import {setRepo} from './db'
|
import {List, Text} from 'react-native-paper'
|
||||||
import GymSet from './gym-set'
|
import GymSet from './gym-set'
|
||||||
import {HomePageParams} from './home-page-params'
|
import {HomePageParams} from './home-page-params'
|
||||||
import Settings from './settings'
|
import Settings from './settings'
|
||||||
import useDark from './use-dark'
|
import useDark from './use-dark'
|
||||||
import {format} from 'date-fns'
|
|
||||||
|
|
||||||
export default function SetItem({
|
export default function SetItem({
|
||||||
item,
|
item,
|
||||||
onRemove,
|
|
||||||
settings,
|
settings,
|
||||||
|
ids,
|
||||||
|
setIds,
|
||||||
}: {
|
}: {
|
||||||
item: GymSet
|
item: GymSet
|
||||||
onRemove: () => void
|
onRemove: () => void
|
||||||
settings: Settings
|
settings: Settings
|
||||||
|
ids: number[]
|
||||||
|
setIds: (value: number[]) => void
|
||||||
}) {
|
}) {
|
||||||
const [showMenu, setShowMenu] = useState(false)
|
|
||||||
const [anchor, setAnchor] = useState({x: 0, y: 0})
|
|
||||||
const dark = useDark()
|
const dark = useDark()
|
||||||
const navigation = useNavigation<NavigationProp<HomePageParams>>()
|
const navigation = useNavigation<NavigationProp<HomePageParams>>()
|
||||||
|
|
||||||
const remove = useCallback(async () => {
|
const longPress = useCallback(() => {
|
||||||
console.log(`${SetItem.name}.remove:`, {id: item.id})
|
if (ids.length > 0) return
|
||||||
if (typeof item.id === 'number') await setRepo.delete(item.id)
|
setIds([item.id])
|
||||||
setShowMenu(false)
|
}, [ids.length, item.id, setIds])
|
||||||
onRemove()
|
|
||||||
}, [setShowMenu, onRemove, item.id])
|
|
||||||
|
|
||||||
const copy = useCallback(() => {
|
const press = useCallback(() => {
|
||||||
const set: GymSet = {...item}
|
if (ids.length === 0) return navigation.navigate('EditSet', {set: item})
|
||||||
delete set.id
|
const removing = ids.find(id => id === item.id)
|
||||||
setShowMenu(false)
|
if (removing) setIds(ids.filter(id => id !== item.id))
|
||||||
navigation.navigate('EditSet', {set})
|
else setIds([...ids, item.id])
|
||||||
}, [navigation, item])
|
}, [ids, item, navigation, setIds])
|
||||||
|
|
||||||
const longPress = useCallback(
|
const backgroundColor = useMemo(() => {
|
||||||
(e: GestureResponderEvent) => {
|
if (!ids.includes(item.id)) return
|
||||||
setAnchor({x: e.nativeEvent.pageX, y: e.nativeEvent.pageY})
|
if (dark) return '#c2c2c2'
|
||||||
setShowMenu(true)
|
return '#c2c2c2'
|
||||||
},
|
}, [dark, ids, item.id])
|
||||||
[setShowMenu, setAnchor],
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<List.Item
|
<List.Item
|
||||||
onPress={() => navigation.navigate('EditSet', {set: item})}
|
onPress={press}
|
||||||
title={item.name}
|
title={item.name}
|
||||||
description={`${item.reps} x ${item.weight}${item.unit || 'kg'}`}
|
description={`${item.reps} x ${item.weight}${item.unit || 'kg'}`}
|
||||||
onLongPress={longPress}
|
onLongPress={longPress}
|
||||||
|
style={{backgroundColor}}
|
||||||
left={() =>
|
left={() =>
|
||||||
settings.images &&
|
settings.images &&
|
||||||
item.image && (
|
item.image && (
|
||||||
|
@ -69,14 +66,6 @@ export default function SetItem({
|
||||||
{format(new Date(item.created), settings.date || 'P')}
|
{format(new Date(item.created), settings.date || 'P')}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
<Menu
|
|
||||||
anchor={anchor}
|
|
||||||
visible={showMenu}
|
|
||||||
onDismiss={() => setShowMenu(false)}>
|
|
||||||
<Menu.Item icon="content-copy" onPress={copy} title="Copy" />
|
|
||||||
<Divider />
|
|
||||||
<Menu.Item icon="delete" onPress={remove} title="Delete" />
|
|
||||||
</Menu>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -24,6 +24,7 @@ export default function SetList() {
|
||||||
const [term, setTerm] = useState('')
|
const [term, setTerm] = useState('')
|
||||||
const [end, setEnd] = useState(false)
|
const [end, setEnd] = useState(false)
|
||||||
const [settings, setSettings] = useState<Settings>()
|
const [settings, setSettings] = useState<Settings>()
|
||||||
|
const [ids, setIds] = useState<number[]>([])
|
||||||
const navigation = useNavigation<NavigationProp<HomePageParams>>()
|
const navigation = useNavigation<NavigationProp<HomePageParams>>()
|
||||||
|
|
||||||
const refresh = useCallback(async (value: string) => {
|
const refresh = useCallback(async (value: string) => {
|
||||||
|
@ -58,9 +59,11 @@ export default function SetList() {
|
||||||
item={item}
|
item={item}
|
||||||
key={item.id}
|
key={item.id}
|
||||||
onRemove={() => refresh(term)}
|
onRemove={() => refresh(term)}
|
||||||
|
ids={ids}
|
||||||
|
setIds={setIds}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
[refresh, term, settings],
|
[refresh, term, settings, ids],
|
||||||
)
|
)
|
||||||
|
|
||||||
const next = useCallback(async () => {
|
const next = useCallback(async () => {
|
||||||
|
@ -101,7 +104,7 @@ export default function SetList() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DrawerHeader name="Home" />
|
<DrawerHeader name="Home" ids={ids} />
|
||||||
<Page onAdd={onAdd} term={term} search={search}>
|
<Page onAdd={onAdd} term={term} search={search}>
|
||||||
{sets?.length === 0 ? (
|
{sets?.length === 0 ? (
|
||||||
<List.Item
|
<List.Item
|
||||||
|
|
|
@ -5,4 +5,7 @@ export type HomePageParams = {
|
||||||
EditSet: {
|
EditSet: {
|
||||||
set: GymSet
|
set: GymSet
|
||||||
}
|
}
|
||||||
|
EditSets: {
|
||||||
|
ids: number[]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user