713 lines
22 KiB
TypeScript
713 lines
22 KiB
TypeScript
import AuthHeader from '@/components/ui/AuthHeader';
|
|
import { decryptToken } from '@/constants/crypto';
|
|
import { formatPhone, normalizeDigits } from '@/constants/formatPhone';
|
|
import { products_api } from '@/screens/home/lib/api';
|
|
import BottomSheet, { BottomSheetBackdrop, BottomSheetFlatList, BottomSheetTextInput } from '@gorhom/bottom-sheet';
|
|
import { useMutation, useQuery } from '@tanstack/react-query';
|
|
import { Image } from 'expo-image';
|
|
import { LinearGradient } from 'expo-linear-gradient';
|
|
import { useRouter } from 'expo-router';
|
|
import {
|
|
CheckIcon,
|
|
ChevronDown,
|
|
Globe,
|
|
Hash,
|
|
Search,
|
|
UserPlus
|
|
} from 'lucide-react-native';
|
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import {
|
|
ActivityIndicator,
|
|
Keyboard,
|
|
StyleSheet,
|
|
Text,
|
|
TextInput,
|
|
TouchableOpacity,
|
|
View
|
|
} from 'react-native';
|
|
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
import { auth_api, GetInfo } from '../login/lib/api';
|
|
import PhonePrefix from '../login/ui/PhonePrefix';
|
|
import { UseLoginForm } from '../login/ui/UseLoginForm';
|
|
import { useResolveLocation } from './lib/useResolveLocation';
|
|
|
|
export default function RegisterFormScreen() {
|
|
const router = useRouter();
|
|
const { t } = useTranslation();
|
|
const { phone, setPhone } = UseLoginForm();
|
|
const countrySheetRef = useRef<BottomSheet>(null);
|
|
const snapPoints = useMemo(() => ['60%', '90%'], []);
|
|
const [selectedCountry, setSelectedCountry] = useState<string>('UZ');
|
|
const [countrySearch, setCountrySearch] = useState<string>('');
|
|
|
|
const [stir, setStir] = useState('');
|
|
const [info, setInfo] = useState<GetInfo | null>(null);
|
|
const [loading, setLoading] = useState(false);
|
|
const [referal, setReferal] = useState('');
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [token, setTokens] = useState<{ name: string, value: string } | null>(null);
|
|
|
|
const [directorTinInput, setDirectorTinInput] = useState('');
|
|
|
|
// ─── Token ───────────────────────────────────────────────────────────────────
|
|
|
|
const { data } = useQuery({
|
|
queryKey: ["tokens"],
|
|
queryFn: async () => auth_api.get_tokens(),
|
|
select(data) {
|
|
return data.data.data.results;
|
|
},
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (data?.length) {
|
|
const token = data[0];
|
|
const tokenValue = decryptToken(token.value);
|
|
if (tokenValue) {
|
|
setTokens({ name: token.key, value: tokenValue });
|
|
}
|
|
}
|
|
}, [data]);
|
|
|
|
// ─── Location resolver hook ───────────────────────────────────────────────────
|
|
|
|
const {
|
|
location,
|
|
resolve: resolveLocation,
|
|
reset: resetLocation,
|
|
} = useResolveLocation({
|
|
token: token?.value ?? null,
|
|
tokenName: token?.name ?? null,
|
|
});
|
|
|
|
console.log("location", location.district?.id);
|
|
|
|
|
|
// ─── STIR info mutation ───────────────────────────────────────────────────────
|
|
|
|
const { mutate } = useMutation({
|
|
mutationFn: (stir: string) =>
|
|
auth_api.get_info({
|
|
value: stir,
|
|
token: token?.value || "",
|
|
tokenName: token?.name || "",
|
|
}),
|
|
onSuccess: (res) => {
|
|
setInfo(res.data);
|
|
setLoading(false);
|
|
setError(null);
|
|
if (res.data?.address) {
|
|
resolveLocation(res.data.address);
|
|
}
|
|
},
|
|
onError: () => {
|
|
setInfo(null);
|
|
setLoading(false);
|
|
setError("Foydalanuvchi topilmadi");
|
|
resetLocation();
|
|
},
|
|
});
|
|
|
|
// ─── Country list ─────────────────────────────────────────────────────────────
|
|
|
|
const { data: countryResponse, isLoading: countryLoading } = useQuery({
|
|
queryKey: ['country-detail'],
|
|
queryFn: async () => products_api.getStates(),
|
|
select: (res) => res.data?.data || [],
|
|
});
|
|
|
|
// ─── Validation helpers ───────────────────────────────────────────────────────
|
|
|
|
useEffect(() => {
|
|
if (info === null || (stir.length === 9 && info.name && info.fullName)) {
|
|
setError(null);
|
|
} else if (info?.name === null || info?.fullName === null) {
|
|
setError("Sizning shaxsiy ma'lumotlaringiz topilmadi");
|
|
} else if (!info?.selfEmployment && !info?.isItd) {
|
|
setError("Siz o'zini o'zi band qilgan yoki yakka tartibdagi tadbirkorlik bo'lishingiz kerak");
|
|
}
|
|
}, [info]);
|
|
|
|
const hasDirectorTin = info?.directorPinfl && String(info.directorPinfl).length > 0;
|
|
const isDirectorTinValid = !hasDirectorTin || directorTinInput === String(info.directorPinfl);
|
|
const hasValidName = Boolean(info?.name || info?.fullName);
|
|
|
|
const valid =
|
|
phone.length === 9 &&
|
|
(stir.length === 9 || stir.length === 14) &&
|
|
info &&
|
|
hasValidName &&
|
|
isDirectorTinValid &&
|
|
error === null;
|
|
|
|
// ─── Country sheet ────────────────────────────────────────────────────────────
|
|
|
|
const filteredCountries = useMemo(() => {
|
|
if (!countrySearch.trim()) return countryResponse || [];
|
|
const q = countrySearch.toLowerCase().trim();
|
|
return (countryResponse || []).filter((c: any) =>
|
|
c.name?.toLowerCase().includes(q)
|
|
);
|
|
}, [countryResponse, countrySearch]);
|
|
|
|
const openCountrySheet = useCallback(() => {
|
|
Keyboard.dismiss();
|
|
setTimeout(() => {
|
|
countrySheetRef.current?.snapToIndex(0);
|
|
}, 100);
|
|
}, []);
|
|
|
|
const selectedCountryName = useMemo(() => {
|
|
if (!selectedCountry) return t('Tanlang');
|
|
return (
|
|
countryResponse?.find(
|
|
(c: any) => c.flag?.toUpperCase() === selectedCountry
|
|
)?.name || t('Tanlang')
|
|
);
|
|
}, [selectedCountry, countryResponse, t]);
|
|
|
|
const renderBackdrop = useCallback(
|
|
(props: any) => (
|
|
<BottomSheetBackdrop
|
|
{...props}
|
|
appearsOnIndex={0}
|
|
disappearsOnIndex={-1}
|
|
opacity={0.6}
|
|
pressBehavior="close"
|
|
/>
|
|
),
|
|
[]
|
|
);
|
|
|
|
const closeCountrySheet = useCallback(() => {
|
|
countrySheetRef.current?.close();
|
|
setTimeout(() => setCountrySearch(''), 300);
|
|
}, []);
|
|
|
|
// ─── Render ───────────────────────────────────────────────────────────────────
|
|
|
|
return (
|
|
<>
|
|
<KeyboardAwareScrollView
|
|
enableOnAndroid
|
|
enableAutomaticScroll
|
|
extraScrollHeight={120}
|
|
style={styles.keyboardScroll}
|
|
>
|
|
<View
|
|
style={styles.container}
|
|
onStartShouldSetResponder={() => {
|
|
Keyboard.dismiss();
|
|
return false;
|
|
}}
|
|
>
|
|
<LinearGradient
|
|
colors={['#0f172a', '#1e293b', '#334155']}
|
|
start={{ x: 0, y: 0 }}
|
|
end={{ x: 1, y: 1 }}
|
|
style={StyleSheet.absoluteFill}
|
|
/>
|
|
<View style={styles.decorCircle1} />
|
|
<View style={styles.decorCircle2} />
|
|
|
|
<AuthHeader />
|
|
|
|
<SafeAreaView style={{ flex: 1 }} edges={['bottom']}>
|
|
<View style={styles.scrollContent}>
|
|
<View style={styles.header}>
|
|
<View style={styles.iconContainer}>
|
|
<LinearGradient
|
|
colors={['#10b981', '#059669']}
|
|
style={styles.iconGradient}
|
|
start={{ x: 0, y: 0 }}
|
|
end={{ x: 1, y: 1 }}
|
|
>
|
|
<UserPlus size={32} color="#fff" />
|
|
</LinearGradient>
|
|
</View>
|
|
<Text style={styles.title}>{t("Ro'yxatdan o'tish")}</Text>
|
|
</View>
|
|
|
|
<View style={styles.card}>
|
|
<View style={styles.formGap}>
|
|
|
|
{/* Country */}
|
|
<View>
|
|
<Text style={styles.label}>{t('Davlat')}</Text>
|
|
<TouchableOpacity
|
|
style={[styles.input, styles.inputDisabled]}
|
|
onPress={openCountrySheet}
|
|
activeOpacity={0.7}
|
|
testID="country-select"
|
|
disabled
|
|
>
|
|
{countryLoading ? (
|
|
<ActivityIndicator size="small" color="#3b82f6" style={{ flex: 1 }} />
|
|
) : (
|
|
<>
|
|
<Image
|
|
source={{ uri: `https://flagcdn.com/w320/${selectedCountry.toLowerCase()}.png` }}
|
|
style={{ width: 30, height: 15 }}
|
|
resizeMode="cover"
|
|
/>
|
|
<Text
|
|
style={[styles.textInput, { color: '#94a3b8' }]}
|
|
numberOfLines={1}
|
|
>
|
|
{selectedCountryName}
|
|
</Text>
|
|
</>
|
|
)}
|
|
<ChevronDown size={18} color={'#cbd5e1'} />
|
|
</TouchableOpacity>
|
|
</View>
|
|
|
|
{/* STIR */}
|
|
<View>
|
|
<Text style={styles.label}>{t('STIR')}</Text>
|
|
<View style={styles.input}>
|
|
<Hash size={18} color="#94a3b8" />
|
|
<TextInput
|
|
value={stir}
|
|
keyboardType="numeric"
|
|
placeholder={t('STIR')}
|
|
placeholderTextColor="#94a3b8"
|
|
style={{ flex: 1, color: "black" }}
|
|
onChangeText={(text) => {
|
|
const v = normalizeDigits(text).slice(0, 14);
|
|
setStir(v);
|
|
if (v.length === 9 || v.length === 14) {
|
|
setLoading(true);
|
|
resetLocation();
|
|
mutate(v);
|
|
}
|
|
}}
|
|
/>
|
|
{loading && <ActivityIndicator size="small" />}
|
|
</View>
|
|
</View>
|
|
|
|
{/* Referal */}
|
|
<View>
|
|
<Text style={styles.label}>{t('Referal')}</Text>
|
|
<View style={styles.input}>
|
|
<Hash size={18} color="#94a3b8" />
|
|
<TextInput
|
|
value={referal}
|
|
placeholder={t('Referal kodi')}
|
|
placeholderTextColor="#94a3b8"
|
|
style={styles.textInput}
|
|
onChangeText={setReferal}
|
|
maxLength={9}
|
|
testID="referal-input"
|
|
/>
|
|
</View>
|
|
</View>
|
|
|
|
{/* Phone */}
|
|
<View>
|
|
<Text style={styles.label}>{t('Telefon raqami')}</Text>
|
|
<View style={styles.input}>
|
|
<PhonePrefix focused={false} />
|
|
<TextInput
|
|
value={formatPhone(phone)}
|
|
placeholder="90 123 45 67"
|
|
placeholderTextColor="#94a3b8"
|
|
keyboardType="phone-pad"
|
|
style={{ flex: 1 }}
|
|
onChangeText={(t) => setPhone(normalizeDigits(t))}
|
|
/>
|
|
</View>
|
|
</View>
|
|
|
|
{/* Director TIN */}
|
|
{hasDirectorTin && (
|
|
<View>
|
|
<Text style={styles.label}>{t('Direktor STIR')}</Text>
|
|
<View
|
|
style={[
|
|
styles.input,
|
|
{ backgroundColor: isDirectorTinValid ? '#f0fdf4' : '#f8fafc' },
|
|
]}
|
|
>
|
|
<Hash size={18} color="#94a3b8" />
|
|
<TextInput
|
|
value={directorTinInput}
|
|
keyboardType="numeric"
|
|
placeholder={t('Direktor STIR')}
|
|
placeholderTextColor="#94a3b8"
|
|
style={{ flex: 1 }}
|
|
maxLength={14}
|
|
onChangeText={(t) => setDirectorTinInput(normalizeDigits(t))}
|
|
/>
|
|
</View>
|
|
{directorTinInput.length === 14 && !isDirectorTinValid && (
|
|
<Text style={styles.error}>{t("Direktor STIR noto'g'ri")}</Text>
|
|
)}
|
|
</View>
|
|
)}
|
|
|
|
{/* Info / Error */}
|
|
{error !== null ? (
|
|
<Text style={styles.notFound}>{t(error)}</Text>
|
|
) : (
|
|
info && hasValidName && (
|
|
<Text style={styles.info}>{info.fullName || info.name}</Text>
|
|
)
|
|
)}
|
|
|
|
{/* Submit */}
|
|
<TouchableOpacity
|
|
disabled={!valid}
|
|
style={[styles.btn, !valid && styles.disabled]}
|
|
onPress={() => {
|
|
if (error === null) {
|
|
router.push({
|
|
pathname: '/(auth)/select-category',
|
|
params: {
|
|
phone,
|
|
first_name: stir.length === 9 ? info?.director : info?.fullName,
|
|
last_name: stir.length === 9 ? info?.director : info?.fullName,
|
|
company_name: info?.name,
|
|
district: location.district?.id,
|
|
address: location.district?.id,
|
|
director_full_name: stir.length === 9 ? info?.director : info?.fullName,
|
|
stir,
|
|
referal,
|
|
person_type:
|
|
stir.length === 9
|
|
? 'legal_entity'
|
|
: info?.selfEmployment
|
|
? 'band'
|
|
: 'ytt',
|
|
},
|
|
});
|
|
}
|
|
}}
|
|
>
|
|
<Text style={styles.btnText}>{t('Davom etish')}</Text>
|
|
</TouchableOpacity>
|
|
|
|
</View>
|
|
</View>
|
|
</View>
|
|
</SafeAreaView>
|
|
</View>
|
|
</KeyboardAwareScrollView>
|
|
|
|
{/* Country BottomSheet */}
|
|
<BottomSheet
|
|
ref={countrySheetRef}
|
|
index={-1}
|
|
snapPoints={snapPoints}
|
|
enablePanDownToClose={true}
|
|
enableDynamicSizing={false}
|
|
enableOverDrag={false}
|
|
backdropComponent={renderBackdrop}
|
|
backgroundStyle={styles.bottomSheetBg}
|
|
handleIndicatorStyle={styles.handleIndicator}
|
|
android_keyboardInputMode="adjustResize"
|
|
keyboardBehavior="interactive"
|
|
keyboardBlurBehavior="restore"
|
|
>
|
|
<View style={styles.sheetHeader}>
|
|
<Text style={styles.sheetTitle}>{t('Davlat')}</Text>
|
|
</View>
|
|
|
|
<View style={styles.searchContainer}>
|
|
<Search size={16} color="#94a3b8" />
|
|
<BottomSheetTextInput
|
|
value={countrySearch}
|
|
onChangeText={setCountrySearch}
|
|
placeholder={t('Qidirish...')}
|
|
placeholderTextColor="#94a3b8"
|
|
style={styles.searchInput}
|
|
clearButtonMode="while-editing"
|
|
autoCorrect={false}
|
|
/>
|
|
</View>
|
|
|
|
<BottomSheetFlatList
|
|
data={filteredCountries}
|
|
keyExtractor={(item: any) => item.id?.toString()}
|
|
contentContainerStyle={styles.listContainer}
|
|
showsVerticalScrollIndicator={false}
|
|
keyboardShouldPersistTaps="handled"
|
|
ListEmptyComponent={
|
|
<View style={styles.emptyList}>
|
|
<Text style={styles.emptyListText}>{t('Natija topilmadi')}</Text>
|
|
</View>
|
|
}
|
|
renderItem={({ item }: { item: any }) => {
|
|
const isSelected = item.flag?.toUpperCase() === selectedCountry;
|
|
const flagCode = item.flag ? item.flag.toLowerCase() : '';
|
|
return (
|
|
<TouchableOpacity
|
|
style={[styles.listItem, isSelected && styles.selectedListItem]}
|
|
onPress={() => {
|
|
setSelectedCountry(item.flag?.toUpperCase());
|
|
closeCountrySheet();
|
|
}}
|
|
activeOpacity={0.7}
|
|
>
|
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 10, flex: 1 }}>
|
|
{flagCode ? (
|
|
<Image
|
|
source={{ uri: `https://flagcdn.com/w320/${flagCode}.png` }}
|
|
style={{ width: 34, height: 22, borderRadius: 2 }}
|
|
/>
|
|
) : (
|
|
<Globe size={20} color={isSelected ? '#2563eb' : '#94a3b8'} />
|
|
)}
|
|
<Text style={[styles.listItemText, isSelected && styles.selectedListItemText]}>
|
|
{item.name}
|
|
</Text>
|
|
</View>
|
|
{isSelected && (
|
|
<View style={styles.checkmark}>
|
|
<CheckIcon color="#3b82f6" strokeWidth={2.5} size={16} />
|
|
</View>
|
|
)}
|
|
</TouchableOpacity>
|
|
);
|
|
}}
|
|
/>
|
|
</BottomSheet>
|
|
</>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
keyboardScroll: {
|
|
flex: 1,
|
|
backgroundColor: '#0f172a',
|
|
},
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: '#0f172a',
|
|
minHeight: '100%',
|
|
},
|
|
scrollContent: {
|
|
flexGrow: 1,
|
|
paddingHorizontal: 24,
|
|
paddingBottom: 40,
|
|
paddingTop: 10,
|
|
},
|
|
header: {
|
|
alignItems: 'center',
|
|
marginBottom: 28,
|
|
},
|
|
iconContainer: {
|
|
marginBottom: 16,
|
|
},
|
|
iconGradient: {
|
|
width: 72,
|
|
height: 72,
|
|
borderRadius: 22,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
shadowColor: '#10b981',
|
|
shadowOffset: { width: 0, height: 8 },
|
|
shadowOpacity: 0.3,
|
|
shadowRadius: 12,
|
|
elevation: 8,
|
|
},
|
|
title: {
|
|
fontSize: 26,
|
|
fontWeight: '800' as const,
|
|
color: '#ffffff',
|
|
marginBottom: 8,
|
|
letterSpacing: 0.5,
|
|
},
|
|
card: {
|
|
backgroundColor: '#ffffff',
|
|
borderRadius: 28,
|
|
padding: 24,
|
|
shadowColor: '#000',
|
|
shadowOffset: { width: 0, height: 10 },
|
|
shadowOpacity: 0.3,
|
|
shadowRadius: 20,
|
|
elevation: 10,
|
|
},
|
|
formGap: {
|
|
gap: 16,
|
|
},
|
|
label: {
|
|
fontWeight: '700' as const,
|
|
color: '#475569',
|
|
marginBottom: 6,
|
|
fontSize: 14,
|
|
},
|
|
input: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
backgroundColor: '#f8fafc',
|
|
borderRadius: 14,
|
|
paddingHorizontal: 12,
|
|
height: 52,
|
|
borderWidth: 1,
|
|
borderColor: '#e2e8f0',
|
|
gap: 8,
|
|
},
|
|
inputDisabled: {
|
|
backgroundColor: '#f1f5f9',
|
|
borderColor: '#e2e8f0',
|
|
},
|
|
textInput: {
|
|
flex: 1,
|
|
fontSize: 15,
|
|
color: '#1e293b',
|
|
},
|
|
bottomSheetBg: {
|
|
backgroundColor: '#ffffff',
|
|
borderTopLeftRadius: 24,
|
|
borderTopRightRadius: 24,
|
|
shadowColor: '#000',
|
|
shadowOffset: { width: 0, height: -2 },
|
|
shadowOpacity: 0.1,
|
|
shadowRadius: 8,
|
|
elevation: 5,
|
|
},
|
|
handleIndicator: {
|
|
width: 40,
|
|
height: 4,
|
|
borderRadius: 2,
|
|
backgroundColor: '#cbd5e1',
|
|
},
|
|
sheetHeader: {
|
|
paddingHorizontal: 20,
|
|
paddingVertical: 16,
|
|
borderBottomWidth: 1,
|
|
borderBottomColor: '#e2e8f0',
|
|
},
|
|
sheetTitle: {
|
|
fontSize: 18,
|
|
fontWeight: '700',
|
|
color: '#0f172a',
|
|
},
|
|
listContainer: {
|
|
padding: 16,
|
|
paddingBottom: 40,
|
|
},
|
|
listItem: {
|
|
flexDirection: 'row',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
padding: 14,
|
|
borderRadius: 12,
|
|
marginBottom: 8,
|
|
borderWidth: 1,
|
|
backgroundColor: '#ffffff',
|
|
borderColor: '#e2e8f0',
|
|
},
|
|
selectedListItem: {
|
|
backgroundColor: '#eff6ff',
|
|
borderColor: '#3b82f6',
|
|
},
|
|
listItemText: {
|
|
fontSize: 15,
|
|
fontWeight: '500',
|
|
color: '#1e293b',
|
|
},
|
|
selectedListItemText: {
|
|
color: '#2563eb',
|
|
fontWeight: '600',
|
|
},
|
|
checkmark: {
|
|
width: 24,
|
|
height: 24,
|
|
borderRadius: 12,
|
|
backgroundColor: '#dbeafe',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
searchContainer: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
backgroundColor: '#f1f5f9',
|
|
borderRadius: 12,
|
|
marginHorizontal: 16,
|
|
marginVertical: 12,
|
|
paddingHorizontal: 12,
|
|
gap: 8,
|
|
height: 44,
|
|
borderWidth: 1,
|
|
borderColor: '#e2e8f0',
|
|
},
|
|
searchInput: {
|
|
flex: 1,
|
|
fontSize: 15,
|
|
color: '#1e293b',
|
|
paddingVertical: 0,
|
|
},
|
|
emptyList: {
|
|
alignItems: 'center',
|
|
paddingVertical: 32,
|
|
},
|
|
emptyListText: {
|
|
fontSize: 14,
|
|
color: '#94a3b8',
|
|
fontWeight: '500',
|
|
},
|
|
btn: {
|
|
height: 54,
|
|
backgroundColor: '#2563eb',
|
|
borderRadius: 16,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
shadowColor: '#2563eb',
|
|
shadowOffset: { width: 0, height: 4 },
|
|
shadowOpacity: 0.3,
|
|
shadowRadius: 8,
|
|
elevation: 6,
|
|
},
|
|
disabled: {
|
|
opacity: 0.45,
|
|
},
|
|
btnText: {
|
|
color: '#fff',
|
|
fontWeight: '800' as const,
|
|
fontSize: 16,
|
|
},
|
|
decorCircle1: {
|
|
position: 'absolute',
|
|
top: -150,
|
|
right: -100,
|
|
width: 400,
|
|
height: 400,
|
|
borderRadius: 200,
|
|
backgroundColor: 'rgba(59, 130, 246, 0.1)',
|
|
},
|
|
decorCircle2: {
|
|
position: 'absolute',
|
|
bottom: -100,
|
|
left: -150,
|
|
width: 350,
|
|
height: 350,
|
|
borderRadius: 175,
|
|
backgroundColor: 'rgba(16, 185, 129, 0.08)',
|
|
},
|
|
info: {
|
|
padding: 12,
|
|
borderRadius: 12,
|
|
fontWeight: '700',
|
|
backgroundColor: '#f0fdf4',
|
|
},
|
|
error: {
|
|
color: '#dc2626',
|
|
fontSize: 12,
|
|
marginTop: 4,
|
|
fontWeight: '600',
|
|
},
|
|
notFound: {
|
|
backgroundColor: '#fef2f2',
|
|
padding: 12,
|
|
borderRadius: 12,
|
|
fontWeight: '700',
|
|
color: '#dc2626',
|
|
borderWidth: 1,
|
|
borderColor: '#fecaca',
|
|
},
|
|
}); |