Files
info-target-mobile/screens/profile/ui/AddEmployee.tsx
Samandar Turgunboyev ab363ca3b9 bug fixed
2026-03-02 13:22:55 +05:00

219 lines
6.2 KiB
TypeScript

import { useTheme } from '@/components/ThemeContext';
import { formatPhone, normalizeDigits } from '@/constants/formatPhone';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { AxiosError } from 'axios';
import { useRouter } from 'expo-router';
import { ArrowLeft, Check } from 'lucide-react-native';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
ActivityIndicator,
Alert,
Pressable,
ScrollView,
StyleSheet,
Text,
TextInput,
View
} from 'react-native';
import { Toast } from 'toastify-react-native';
import { user_api } from '../lib/api';
export default function AddEmployee() {
const router = useRouter();
const queryClient = useQueryClient();
const { isDark } = useTheme();
const { t } = useTranslation();
const theme = {
background: isDark ? '#0f172a' : '#f8fafc',
inputBg: isDark ? '#1e293b' : '#f1f5f9',
inputBorder: isDark ? '#1e293b' : '#e2e8f0',
text: isDark ? '#f8fafc' : '#0f172a',
textSecondary: isDark ? '#64748b' : '#94a3b8',
primary: '#3b82f6',
placeholder: isDark ? '#94a3b8' : '#94a3b8',
divider: isDark ? '#fff' : '#cbd5e1',
};
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [phoneNumber, setPhoneNumber] = useState('');
const [focused, setFocused] = useState(false);
const { mutate, isPending } = useMutation({
mutationFn: (body: { first_name: string; last_name: string; phone: string }) =>
user_api.create_employee(body),
onSuccess: () => {
router.push('/profile/employees');
queryClient.refetchQueries({ queryKey: ['employees_list'] });
},
onError: (err: AxiosError) => {
const errMessage = (err.response?.data as { data: { phone: string[] } }).data.phone[0];
Alert.alert(t('Xatolik yuz berdi'), errMessage || t('Xatolik yuz berdi'));
},
});
const handleChange = (text: string) => {
setPhoneNumber(normalizeDigits(text));
};
const handleSave = () => {
if (!firstName.trim() || !lastName.trim() || !phoneNumber.trim()) {
Toast.info(t("Barcha maydonlarni to'ldiring"));
return;
}
mutate({
first_name: firstName.trim(),
last_name: lastName.trim(),
phone: `998${phoneNumber.trim()}`,
});
};
return (
<View style={[styles.container, { backgroundColor: theme.background }]}>
<View style={styles.topHeader}>
<Pressable onPress={() => router.push('/profile/employees')}>
<ArrowLeft color={theme.text} />
</Pressable>
<Text style={[styles.headerTitle, { color: theme.text }]}>{t("Xodim qo'shish")}</Text>
<Pressable onPress={handleSave} disabled={isPending}>
{isPending ? (
<ActivityIndicator size={'small'} />
) : (
<Check size={26} color={theme.primary} />
)}
</Pressable>
</View>
<ScrollView style={styles.content} showsVerticalScrollIndicator={false}>
<View style={styles.form}>
<View style={styles.field}>
<Text style={[styles.label, { color: theme.textSecondary }]}>{t('Ism')}</Text>
<TextInput
style={[styles.input, { backgroundColor: theme.inputBg, color: theme.text }]}
value={firstName}
onChangeText={setFirstName}
placeholder={t('Ism kiriting')}
placeholderTextColor={theme.placeholder}
/>
</View>
<View style={styles.field}>
<Text style={[styles.label, { color: theme.textSecondary }]}>{t('Familiya')}</Text>
<TextInput
style={[styles.input, { backgroundColor: theme.inputBg, color: theme.text }]}
value={lastName}
onChangeText={setLastName}
placeholder={t('Familiya kiriting')}
placeholderTextColor={theme.placeholder}
/>
</View>
<View
style={[
styles.inputContainer,
{ backgroundColor: theme.inputBg, borderColor: theme.inputBorder },
focused && styles.inputFocused,
]}
>
<View style={styles.prefixContainer}>
<Text style={[styles.prefix, { color: theme.text }, focused && styles.prefixFocused]}>
+998
</Text>
<View style={[styles.divider, { backgroundColor: theme.divider }]} />
</View>
<TextInput
value={formatPhone(phoneNumber)}
onChangeText={handleChange}
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}
keyboardType="phone-pad"
placeholder="90 123 45 67"
placeholderTextColor={theme.placeholder}
style={[styles.input, { color: theme.text }]}
maxLength={12}
/>
</View>
</View>
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
content: {
flex: 1,
},
saveButton: {
fontSize: 16,
fontWeight: '600',
paddingHorizontal: 8,
},
form: {
padding: 16,
gap: 20,
},
field: {
gap: 12,
},
label: {
fontSize: 13,
fontWeight: '600',
textTransform: 'uppercase',
letterSpacing: 0.5,
},
input: {
borderRadius: 16,
padding: 16,
fontSize: 17,
fontWeight: '600',
},
inputContainer: {
flexDirection: 'row',
alignItems: 'center',
borderRadius: 14,
borderWidth: 2,
paddingHorizontal: 16,
height: 56,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.05,
shadowRadius: 8,
elevation: 2,
},
inputFocused: {
shadowOpacity: 0.15,
shadowRadius: 12,
elevation: 4,
},
prefixContainer: {
flexDirection: 'row',
alignItems: 'center',
marginRight: 12,
},
prefix: {
fontSize: 16,
fontWeight: '600',
letterSpacing: 0.3,
},
prefixFocused: {},
divider: {
width: 1.5,
height: 24,
marginLeft: 12,
},
topHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
padding: 16,
alignItems: 'center',
},
headerTitle: { fontSize: 18, fontWeight: '700' },
});