Files
zellyy-finance/src/components/auth/LoginForm.tsx
hansoo 9851627ff1 feat: Add CI/CD pipeline and code quality improvements
- Add GitHub Actions workflow for automated CI/CD
- Configure Node.js 18.x and 20.x matrix testing
- Add TypeScript type checking step
- Add ESLint code quality checks with enhanced rules
- Add Prettier formatting verification
- Add production build validation
- Upload build artifacts for deployment
- Set up automated testing on push/PR
- Replace console.log with environment-aware logger
- Add pre-commit hooks for code quality
- Exclude archive folder from linting

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-12 15:27:54 +09:00

154 lines
5.0 KiB
TypeScript

import React from "react";
import { Link } from "react-router-dom";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import {
ArrowRight,
Mail,
KeyRound,
Eye,
EyeOff,
AlertTriangle,
Loader2,
} from "lucide-react";
interface LoginFormProps {
email: string;
setEmail: (email: string) => void;
password: string;
setPassword: (password: string) => void;
showPassword: boolean;
setShowPassword: (show: boolean) => void;
isLoading: boolean;
isSettingUpTables?: boolean;
loginError: string | null;
handleLogin: (e: React.FormEvent) => Promise<void>;
}
const LoginForm: React.FC<LoginFormProps> = ({
email,
setEmail,
password,
setPassword,
showPassword,
setShowPassword,
isLoading,
isSettingUpTables = false,
loginError,
handleLogin,
}) => {
// CORS 또는 JSON 관련 오류인지 확인
const isCorsOrJsonError =
loginError &&
(loginError.includes("JSON") ||
loginError.includes("CORS") ||
loginError.includes("프록시") ||
loginError.includes("서버 응답") ||
loginError.includes("네트워크") ||
loginError.includes("404") ||
loginError.includes("Not Found"));
return (
<div className="neuro-flat p-8 mb-6">
<form onSubmit={handleLogin}>
<div className="space-y-6">
<div className="space-y-2">
<Label htmlFor="email" className="text-base">
</Label>
<div className="relative">
<Mail className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500 h-5 w-5" />
<Input
id="email"
type="email"
placeholder="your@email.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="pl-10 neuro-pressed"
/>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="password" className="text-base">
</Label>
<div className="relative">
<KeyRound className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-500 h-5 w-5" />
<Input
id="password"
type={showPassword ? "text" : "password"}
placeholder="••••••••"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="pl-10 neuro-pressed"
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-500"
>
{showPassword ? (
<EyeOff className="h-5 w-5" />
) : (
<Eye className="h-5 w-5" />
)}
</button>
</div>
</div>
{loginError && (
<div
className={`p-3 ${isCorsOrJsonError ? "bg-amber-50 text-amber-800" : "bg-red-50 text-red-600"} rounded-md text-sm`}
>
<div className="flex items-start gap-2">
<AlertTriangle className="h-5 w-5 flex-shrink-0 mt-0.5 text-amber-500" />
<div>
<p className="font-medium">{loginError}</p>
{isCorsOrJsonError && (
<ul className="mt-2 list-disc pl-5 text-xs space-y-1 text-amber-700">
<li>
CORS .
</li>
<li>
HTTPS URL을 Supabase .
</li>
<li> .</li>
</ul>
)}
</div>
</div>
</div>
)}
<div className="text-right">
<Link
to="/forgot-password"
className="text-sm text-neuro-income hover:underline"
>
?
</Link>
</div>
<Button
type="submit"
disabled={isLoading || isSettingUpTables}
className="w-full hover:bg-neuro-income/80 text-white h-auto bg-neuro-income text-lg py-[10px]"
>
{isLoading
? "로그인 중..."
: isSettingUpTables
? "데이터베이스 설정 중..."
: "로그인"}
{!isLoading && !isSettingUpTables ? (
<ArrowRight className="ml-2 h-5 w-5" />
) : (
<Loader2 className="ml-2 h-5 w-5 animate-spin" />
)}
</Button>
</div>
</form>
</div>
);
};
export default LoginForm;