Files
imexmobile/components/job-status-selector/job-status-selector.jsx
2025-11-24 10:25:24 -08:00

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;