141 lines
3.3 KiB
JavaScript
141 lines
3.3 KiB
JavaScript
import { UPDATE_JOB_STATUS } from "@/graphql/jobs.queries";
|
|
import { useMutation } from "@apollo/client";
|
|
import * as Haptics from "expo-haptics";
|
|
import { useLocalSearchParams } from "expo-router";
|
|
import React, { useCallback, useState } from "react";
|
|
import { FlatList, StyleSheet, View } from "react-native";
|
|
import {
|
|
Button,
|
|
Divider,
|
|
List,
|
|
Modal,
|
|
Portal,
|
|
Text,
|
|
useTheme,
|
|
} from "react-native-paper";
|
|
|
|
export const JobStatusSelector = ({
|
|
statuses,
|
|
currentStatus,
|
|
onSelect,
|
|
label = "Change Status",
|
|
disabled = false,
|
|
}) => {
|
|
const { jobId } = useLocalSearchParams();
|
|
|
|
const theme = useTheme();
|
|
const [visible, setVisible] = useState(false);
|
|
const show = () => setVisible(true);
|
|
const hide = () => setVisible(false);
|
|
|
|
const [updateJobStatus] = useMutation(UPDATE_JOB_STATUS);
|
|
|
|
const handleSelect = useCallback(
|
|
async (status) => {
|
|
Haptics.selectionAsync().catch(() => {});
|
|
hide();
|
|
await updateJobStatus({
|
|
variables: {
|
|
jobId,
|
|
status,
|
|
},
|
|
});
|
|
if (onSelect && typeof onSelect === "function") onSelect(status);
|
|
},
|
|
[onSelect, jobId, updateJobStatus]
|
|
);
|
|
|
|
return (
|
|
<View style={styles.root}>
|
|
<Button
|
|
mode="outlined"
|
|
icon="playlist-edit"
|
|
onPress={show}
|
|
disabled={disabled || statuses.length === 0}
|
|
style={styles.trigger}
|
|
>
|
|
{currentStatus || label}
|
|
</Button>
|
|
<Portal>
|
|
<Modal
|
|
visible={visible}
|
|
onDismiss={hide}
|
|
contentContainerStyle={[
|
|
{ backgroundColor: theme.colors.surface },
|
|
styles.modalContainer,
|
|
]}
|
|
>
|
|
<Text variant="titleMedium" style={styles.modalTitle}>
|
|
{label}
|
|
</Text>
|
|
<Divider />
|
|
<FlatList
|
|
data={statuses}
|
|
keyExtractor={(item) => item}
|
|
renderItem={({ item }) => {
|
|
const selected = item === currentStatus;
|
|
return (
|
|
<List.Item
|
|
title={item}
|
|
onPress={() => handleSelect(item)}
|
|
style={selected ? styles.selectedItem : undefined}
|
|
titleStyle={selected ? { fontWeight: "600" } : undefined}
|
|
left={(props) =>
|
|
selected ? <List.Icon {...props} icon="check" /> : null
|
|
}
|
|
/>
|
|
);
|
|
}}
|
|
ItemSeparatorComponent={() => <Divider />}
|
|
style={styles.list}
|
|
keyboardShouldPersistTaps="handled"
|
|
/>
|
|
<Button
|
|
onPress={hide}
|
|
style={styles.closeBtn}
|
|
mode="text"
|
|
icon="close"
|
|
>
|
|
Close
|
|
</Button>
|
|
</Modal>
|
|
</Portal>
|
|
</View>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
root: {
|
|
alignSelf: "flex-start",
|
|
paddingTop: 8,
|
|
},
|
|
trigger: {
|
|
minWidth: 140,
|
|
},
|
|
modalContainer: {
|
|
marginHorizontal: 24,
|
|
borderRadius: 16,
|
|
paddingVertical: 12,
|
|
paddingHorizontal: 8,
|
|
height: "60%",
|
|
display: "flex",
|
|
},
|
|
modalTitle: {
|
|
paddingHorizontal: 12,
|
|
paddingBottom: 8,
|
|
},
|
|
list: {
|
|
marginTop: 4,
|
|
flex: 1,
|
|
},
|
|
selectedItem: {
|
|
backgroundColor: "rgba(0,0,0,0.05)",
|
|
},
|
|
closeBtn: {
|
|
marginTop: 8,
|
|
alignSelf: "flex-end",
|
|
},
|
|
});
|
|
|
|
export default JobStatusSelector;
|