Varad Bakshi
Fresh upload
e7427b5
Raw
History Blame Contribute Delete
12.2 kB
import { useState, useEffect } from "react";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Badge } from "@/components/ui/badge";
import { User, Phone, Lock, Shield, Leaf, Users } from "lucide-react";
import { useToast } from "@/hooks/use-toast";
import { userStorage, type UserProfile } from "@/lib/userStorage";
import logoImage from "@assets/ChatGPT Image Jun 6, 2025, 02_19_36 PM.png";
interface AuthProps {
onLogin: (user: UserProfile) => void;
isOpen: boolean;
}
export default function UserAuth({ onLogin, isOpen }: AuthProps) {
const [isLoginMode, setIsLoginMode] = useState(true);
const [name, setName] = useState("");
const [phone, setPhone] = useState("");
const [organization, setOrganization] = useState("");
const [role, setRole] = useState<UserProfile['role']>('engineer');
const [isLoading, setIsLoading] = useState(false);
const [recentUsers, setRecentUsers] = useState<UserProfile[]>([]);
const { toast } = useToast();
useEffect(() => {
loadRecentUsers();
}, []);
const loadRecentUsers = async () => {
try {
const users = await userStorage.getRecentUsers();
setRecentUsers(users.slice(0, 3)); // Show last 3 users
} catch (error) {
console.warn('Could not load recent users:', error);
}
};
const validatePhone = (phoneNumber: string): boolean => {
return userStorage.validatePhoneNumber(phoneNumber);
};
const handleLogin = async () => {
if (!phone.trim()) {
toast({
title: "फोन नंबर आवश्यक / Phone Required",
description: "कृपया अपना फोन नंबर दर्ज करें / Please enter your phone number",
variant: "destructive"
});
return;
}
if (!validatePhone(phone)) {
toast({
title: "अमान्य फोन नंबर / Invalid Phone",
description: "कृपया 10 अंकों का वैध फोन नंबर दर्ज करें / Please enter a valid 10-digit phone number",
variant: "destructive"
});
return;
}
setIsLoading(true);
try {
// Check if user exists
let user = await userStorage.getUserByPhone(phone);
if (user && isLoginMode) {
// Existing user login
const session = userStorage.createSession(user);
toast({
title: `स्वागत है ${user.name} / Welcome ${user.name}`,
description: "सफलतापूर्वक लॉग इन हो गए / Successfully logged in"
});
onLogin(session.user);
} else if (!user && !isLoginMode) {
// New user registration
if (!name.trim()) {
toast({
title: "नाम आवश्यक / Name Required",
description: "कृपया अपना नाम दर्ज करें / Please enter your name",
variant: "destructive"
});
setIsLoading(false);
return;
}
const newUser = await userStorage.createUser({
name: name.trim(),
phone: phone.trim(),
organization: organization.trim() || undefined,
role,
});
const session = userStorage.createSession(newUser);
toast({
title: `खाता बनाया गया / Account Created`,
description: `स्वागत है ${newUser.name} / Welcome ${newUser.name}`
});
onLogin(session.user);
} else if (user && !isLoginMode) {
// User exists but trying to register
toast({
title: "उपयोगकर्ता मौजूद है / User Exists",
description: "यह फोन नंबर पहले से पंजीकृत है / This phone number is already registered",
variant: "destructive"
});
} else {
// User doesn't exist but trying to login
toast({
title: "उपयोगकर्ता नहीं मिला / User Not Found",
description: "कृपया पहले खाता बनाएं / Please create an account first",
variant: "destructive"
});
}
} catch (error) {
toast({
title: "त्रुटि / Error",
description: error instanceof Error ? error.message : "कृपया पुनः प्रयास करें / Please try again",
variant: "destructive"
});
}
setIsLoading(false);
};
const handleQuickLogin = (user: UserProfile) => {
const session = userStorage.createSession(user);
onLogin(session.user);
};
const getRoleDisplay = (role: UserProfile['role']) => {
const roleMap = {
engineer: "इंजीनियर / Engineer",
student: "छात्र / Student",
researcher: "शोधकर्ता / Researcher",
government: "सरकारी / Government",
farmer: "किसान / Farmer",
consultant: "सलाहकार / Consultant"
};
return roleMap[role];
};
const getRoleIcon = (role: UserProfile['role']) => {
const icons = {
engineer: <Shield className="w-4 h-4" />,
student: <User className="w-4 h-4" />,
researcher: <Leaf className="w-4 h-4" />,
government: <Shield className="w-4 h-4" />,
farmer: <Leaf className="w-4 h-4" />,
consultant: <Users className="w-4 h-4" />
};
return icons[role];
};
return (
<Dialog open={isOpen}>
<DialogContent className="max-w-md">
<DialogHeader>
<div className="text-center">
<img
src={logoImage}
alt="Prithvi Guardian AI Logo"
className="w-20 h-20 mx-auto mb-3 rounded-full shadow-md"
/>
<DialogTitle className="text-xl font-bold text-green-800 mb-2">
Prithvi Guardian Ai
</DialogTitle>
</div>
<DialogDescription className="text-center">
पर्यावरण और सिविल इंजीनियरिंग के लिए ऑफलाइन ऐप
<br />
Offline Environmental & Civil Engineering App
</DialogDescription>
</DialogHeader>
<CardContent className="space-y-4">
{/* Recent Users Quick Login */}
{recentUsers.length > 0 && (
<div className="space-y-2">
<Label className="text-sm font-medium">त्वरित लॉगिन / Quick Login</Label>
<div className="space-y-2">
{recentUsers.map((user) => (
<Card
key={user.id}
className="p-3 cursor-pointer hover:bg-gray-50 transition-colors"
onClick={() => handleQuickLogin(user)}
>
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
{getRoleIcon(user.role)}
<div>
<p className="font-medium text-sm">{user.name}</p>
<p className="text-xs text-gray-500">{user.phone}</p>
</div>
</div>
<Badge variant="secondary" className="text-xs">
{getRoleDisplay(user.role).split(' / ')[0]}
</Badge>
</div>
</Card>
))}
</div>
</div>
)}
{/* Login/Register Toggle */}
<div className="flex space-x-2">
<Button
variant={isLoginMode ? "default" : "outline"}
onClick={() => setIsLoginMode(true)}
className="flex-1"
>
लॉग इन / Login
</Button>
<Button
variant={!isLoginMode ? "default" : "outline"}
onClick={() => setIsLoginMode(false)}
className="flex-1"
>
नया खाता / Register
</Button>
</div>
{/* Phone Number Input */}
<div className="space-y-2">
<Label htmlFor="phone">
<Phone className="w-4 h-4 inline mr-2" />
फोन नंबर / Phone Number *
</Label>
<Input
id="phone"
type="tel"
placeholder="9876543210"
value={phone}
onChange={(e) => setPhone(e.target.value)}
maxLength={10}
/>
</div>
{/* Name Input (Registration only) */}
{!isLoginMode && (
<div className="space-y-2">
<Label htmlFor="name">
<User className="w-4 h-4 inline mr-2" />
नाम / Name *
</Label>
<Input
id="name"
type="text"
placeholder="आपका नाम / Your Name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</div>
)}
{/* Organization Input (Registration only) */}
{!isLoginMode && (
<div className="space-y-2">
<Label htmlFor="organization">
संस्था / Organization (Optional)
</Label>
<Input
id="organization"
type="text"
placeholder="कंपनी/कॉलेज का नाम / Company/College Name"
value={organization}
onChange={(e) => setOrganization(e.target.value)}
/>
</div>
)}
{/* Role Selection (Registration only) */}
{!isLoginMode && (
<div className="space-y-2">
<Label>भूमिका / Role</Label>
<div className="grid grid-cols-2 gap-2">
{[
{ key: 'engineer' as const, label: 'इंजीनियर' },
{ key: 'student' as const, label: 'छात्र' },
{ key: 'researcher' as const, label: 'शोधकर्ता' },
{ key: 'government' as const, label: 'सरकारी' },
{ key: 'farmer' as const, label: 'किसान' },
{ key: 'consultant' as const, label: 'सलाहकार' }
].map(({ key, label }) => (
<Button
key={key}
variant={role === key ? "default" : "outline"}
onClick={() => setRole(key)}
className="text-xs py-1"
>
{label}
</Button>
))}
</div>
</div>
)}
{/* Submit Button */}
<Button
onClick={handleLogin}
disabled={isLoading}
className="w-full bg-green-600 hover:bg-green-700"
>
{isLoading ? (
"प्रसंस्करण... / Processing..."
) : isLoginMode ? (
"लॉग इन करें / Login"
) : (
"खाता बनाएं / Create Account"
)}
</Button>
{/* Offline Notice */}
<div className="text-xs text-center text-gray-500 mt-4">
<Lock className="w-3 h-3 inline mr-1" />
पूर्ण ऑफलाइन - कोई डेटा साझा नहीं
<br />
Completely Offline - No Data Shared
</div>
</CardContent>
</DialogContent>
</Dialog>
);
}