EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
LoginForm.tsx
Go to the documentation of this file.
1"use client";
2import { useState } from "react";
3import { apiClient } from "@/lib/client/apiClient";
4
5export default function LoginForm() {
6 const [username, setUsername] = useState("");
7 const [password, setPassword] = useState("");
8 const [storeName, setStoreName] = useState("");
9 const [loading, setLoading] = useState(false);
10 const [error, setError] = useState("");
11
12 async function handleLogin(e: React.FormEvent) {
13 e.preventDefault();
14 setLoading(true);
15 setError("");
16
17 try {
18 // Validate store name
19 if (!storeName.trim()) {
20 setError("Please enter a store name");
21 setLoading(false);
22 return;
23 }
24
25 // Demo mode for testing
26 const demoUsername = process.env.NEXT_PUBLIC_DEMO_USERNAME || "demo";
27 const isDemoMode = process.env.NEXT_PUBLIC_DEMO_MODE === "true";
28
29 if (isDemoMode && (username.toLowerCase() === demoUsername || username === "admin@iig.cwanz.online")) {
30 // Demo mode - redirect without server authentication
31 window.location.href = "/pages/home";
32 return;
33 }
34
35 // Use secure server-side authentication with store name
36 console.log('[LoginForm] Attempting login:', { username, storeName, hasPassword: !!password });
37 const result = await apiClient.login(username, password, storeName.toLowerCase().trim());
38
39 console.log("Login result:", result);
40
41 if (result.success) {
42 // Redirect to specified page or default home
43 const redirectUrl = result.data?.redirect || "/pages/home";
44 console.log("Redirecting to:", redirectUrl);
45 window.location.href = redirectUrl;
46 } else {
47 setError(result.error || "Login failed");
48 }
49 } catch (error) {
50 console.error("Login error:", error);
51 setError("Unable to connect to server");
52 } finally {
53 setLoading(false);
54 }
55 }
56
57 return (
58 <>
59 <form onSubmit={handleLogin} className="space-y-6">
60 {/* Store Name Input */}
61 <div>
62 <label htmlFor="storeName" className="block text-sm font-medium mb-2" style={{ color: '#1f2937' }}>
63 Store Name
64 </label>
65 <input
66 type="text"
67 id="storeName"
68 value={storeName}
69 onChange={(e) => setStoreName(e.target.value)}
70 className="w-full px-3 py-2 rounded-md focus:outline-none focus:ring-2" style={{ border: '1px solid #d1d5db', background: 'white', color: '#1f2937', borderColor: '#d1d5db' }}
71 placeholder="e.g., iig, cowra, griffith, murwillumbah"
72 required
73 />
74 <p className="mt-1 text-xs" style={{ color: '#6b7280' }}>
75 Enter your store name (e.g., "iig" for management, "cowra" for Cowra store)
76 </p>
77 </div>
78
79 <div>
80 <label htmlFor="username" className="block text-sm font-medium mb-2" style={{ color: '#1f2937' }}>
81 Username
82 </label>
83 <input
84 type="text"
85 id="username"
86 value={username}
87 onChange={(e) => setUsername(e.target.value)}
88 className="w-full px-3 py-2 rounded-md focus:outline-none focus:ring-2" style={{ border: '1px solid #d1d5db', background: 'white', color: '#1f2937' }}
89 placeholder="Enter your username"
90 required
91 />
92 </div>
93
94 <div>
95 <label htmlFor="password" className="block text-sm font-medium mb-2" style={{ color: '#1f2937' }}>
96 Password
97 </label>
98 <input
99 type="password"
100 id="password"
101 value={password}
102 onChange={(e) => setPassword(e.target.value)}
103 className="w-full px-3 py-2 rounded-md focus:outline-none focus:ring-2" style={{ border: '1px solid #d1d5db', background: 'white', color: '#1f2937' }}
104 placeholder="Enter your password"
105 required
106 />
107 </div>
108
109 {error && (
110 <div className="px-4 py-3 rounded-md" style={{ background: '#fee2e2', border: '1px solid #fca5a5' }}>
111 <span style={{ color: '#dc2626' }}>{error}</span>
112 </div>
113 )}
114
115 <button
116 type="submit"
117 disabled={loading}
118 className="w-full py-2 px-4 rounded-md hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed"
119 style={{ background: 'linear-gradient(to right, #2563eb, #7c3aed)', color: 'white' }}
120 >
121 {loading ? "Signing in..." : "Sign In"}
122 </button>
123 </form>
124
125 {process.env.NEXT_PUBLIC_DEMO_MODE === "true" && (
126 <div className="mt-6 p-4 rounded-md" style={{ background: '#dbeafe', border: '1px solid #93c5fd' }}>
127 <p className="text-sm" style={{ color: '#1e40af' }}>
128 <strong>Demo Mode:</strong> Use username "demo" with any password to access the demo.
129 </p>
130 </div>
131 )}
132 </>
133 );
134}