Files
fiberops-mobile/app/(auth)/login.tsx
Nemo 4644a3194d feat: major UI/UX overhaul + user management + ticket detail refactor
- 5-tab navigation (Home/Clients/Collect/Tickets/Profile)
- Inline styles throughout (17px min font, SafeAreaView)
- Dashboard fixed to match real API shape
- Ticket detail: 2 tabs (Details + Comments), always-visible comment input
- Installation confirmation: GPS coordinate capture + client location update
- User management screens (Admin only): list, create, detail + role/active toggle
- Tasks folder replaces tickets folder
- Remittance detail: inline styles
- Record payment: prefill from client, live button text
- Icon component with SVG icons
- Color system: primary #0891B2
2026-03-24 10:37:57 +08:00

84 lines
4.1 KiB
TypeScript

import { useState } from 'react';
import { View, Text, TextInput, TouchableOpacity, ActivityIndicator, Alert, KeyboardAvoidingView, Platform } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useLocalSearchParams, router } from 'expo-router';
import { useAuthStore } from '../../stores/authStore';
export default function LoginScreen() {
const { tenantSlug } = useLocalSearchParams<{ tenantSlug: string }>();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [showPassword, setShowPassword] = useState(false);
const { login, isLoading } = useAuthStore();
const handleLogin = async () => {
if (!email.trim() || !password) return Alert.alert('Required', 'Please enter email and password.');
try {
await login(tenantSlug, email.trim(), password);
router.replace('/(app)/dashboard');
} catch (e: any) {
const msg = e?.response?.data?.message ?? 'Login failed. Check your credentials.';
Alert.alert('Login Failed', Array.isArray(msg) ? msg.join('\n') : msg);
}
};
return (
<SafeAreaView style={{ flex: 1, backgroundColor: '#FFF' }}>
<KeyboardAvoidingView style={{ flex: 1 }} behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
<View style={{ flex: 1, justifyContent: 'center', paddingHorizontal: 24 }}>
<TouchableOpacity onPress={() => router.back()} style={{ marginBottom: 32 }} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
<Text style={{ fontSize: 17, fontWeight: '600', color: '#0891B2' }}> Back</Text>
</TouchableOpacity>
<Text style={{ fontSize: 32, fontWeight: '900', color: '#0F172A', letterSpacing: -0.5, marginBottom: 6 }}>Welcome back</Text>
<Text style={{ fontSize: 16, color: '#64748B', marginBottom: 32 }}>
Signing in to <Text style={{ fontWeight: '700', color: '#0F172A' }}>{tenantSlug}</Text>
</Text>
{/* Email */}
<Text style={{ fontSize: 15, fontWeight: '700', color: '#374151', marginBottom: 8 }}>Email</Text>
<TextInput
style={{ backgroundColor: '#F8FAFC', borderWidth: 1.5, borderColor: '#E2E8F0', borderRadius: 14, paddingHorizontal: 18, paddingVertical: 16, fontSize: 17, color: '#0F172A', marginBottom: 16 }}
placeholder="Enter your email"
placeholderTextColor="#94A3B8"
value={email}
onChangeText={setEmail}
autoCapitalize="none"
keyboardType="email-address"
autoFocus
/>
{/* Password */}
<Text style={{ fontSize: 15, fontWeight: '700', color: '#374151', marginBottom: 8 }}>Password</Text>
<View style={{ backgroundColor: '#F8FAFC', borderWidth: 1.5, borderColor: '#E2E8F0', borderRadius: 14, flexDirection: 'row', alignItems: 'center', paddingHorizontal: 18, marginBottom: 28 }}>
<TextInput
style={{ flex: 1, paddingVertical: 16, fontSize: 17, color: '#0F172A' }}
placeholder="Enter your password"
placeholderTextColor="#94A3B8"
value={password}
onChangeText={setPassword}
secureTextEntry={!showPassword}
onSubmitEditing={handleLogin}
/>
<TouchableOpacity onPress={() => setShowPassword(!showPassword)} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
<Text style={{ fontSize: 15, fontWeight: '600', color: '#0891B2' }}>{showPassword ? 'Hide' : 'Show'}</Text>
</TouchableOpacity>
</View>
<TouchableOpacity
style={{ backgroundColor: '#0891B2', borderRadius: 14, paddingVertical: 18, alignItems: 'center' }}
onPress={handleLogin}
disabled={isLoading}
activeOpacity={0.8}
>
{isLoading
? <ActivityIndicator color="#FFF" />
: <Text style={{ color: '#FFF', fontSize: 17, fontWeight: '700' }}>Sign In</Text>
}
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
);
}