LCOV - code coverage report

Current view: | top level - lib/screens/auth - login_screen.dart |  |  | Coverage | Total | Hit
Test: | lcov.info |  | Lines: | 59.4 % | 69 | 41
Test Date: | 2025-08-12 03:21:51 |  | Functions: | - | 0 | 0

                Line data    Source code

           1              : import 'package:flutter/material.dart';
           2              : import 'package:provider/provider.dart';
           3              : import '../../services/auth_service.dart';
           4              : import 'register_screen.dart';
           5              : import 'forgot_password_screen.dart';
           6              :
           7              : class LoginScreen extends StatefulWidget {
           8           48 :   const LoginScreen({super.key});
           9              :
          10            1 :   @override
          11            1 :   State<LoginScreen> createState() => _LoginScreenState();
          12              : }
          13              :
          14              : class _LoginScreenState extends State<LoginScreen> {
          15              :   final _formKey = GlobalKey<FormState>();
          16              :   final _usernameController = TextEditingController();
          17              :   final _passwordController = TextEditingController();
          18              :   bool _isPasswordVisible = false;
          19              :   bool _rememberMe = false;
          20              :
          21            1 :   @override
          22              :   void dispose() {
          23            2 :     _usernameController.dispose();
          24            2 :     _passwordController.dispose();
          25            1 :     super.dispose();
          26              :   }
          27              :
          28              :   // 로그인 처리 함수
          29            0 :   Future<void> _login() async {
          30            0 :     if (_formKey.currentState!.validate()) {
          31            0 :       final authService = Provider.of<AuthService>(context, listen: false);
          32            0 :       final success = await authService.login(
          33            0 :         _usernameController.text.trim(),
          34            0 :         _passwordController.text,
          35              :       );
          36              :
          37            0 :       if (success && mounted) {
          38              :         // 로그인 성공 시 홈 화면으로 이동
          39            0 :         Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false);
          40            0 :       } else if (!success && mounted) {
          41              :         // 로그인 실패 시 스낵바 표시
          42            0 :         ScaffoldMessenger.of(context).showSnackBar(
          43              :           const SnackBar(
          44              :             content: Text('로그인에 실패했습니다. 아이디와 비밀번호를 확인해주세요.'),
          45              :             backgroundColor: Colors.red,
          46              :           ),
          47              :         );
          48              :       }
          49              :     }
          50              :   }
          51              :
          52            1 :   @override
          53              :   Widget build(BuildContext context) {
          54            1 :     final authService = Provider.of<AuthService>(context);
          55              :
          56            1 :     return Scaffold(
          57            1 :       body: SafeArea(
          58            1 :         child: Center(
          59            1 :           child: SingleChildScrollView(
          60              :             padding: const EdgeInsets.all(24.0),
          61            1 :             child: Form(
          62            1 :               key: _formKey,
          63            1 :               child: Column(
          64              :                 mainAxisAlignment: MainAxisAlignment.center,
          65              :                 crossAxisAlignment: CrossAxisAlignment.stretch,
          66            1 :                 children: [
          67              :                   // 로고 이미지
          68            1 :                   Column(
          69            1 :                     children: [
          70            1 :                       Image.asset(
          71              :                         'assets/images/logo.png',
          72              :                         width: 120,
          73              :                         height: 120,
          74              :                       ),
          75              :                       const SizedBox(height: 16),
          76              :                       const Text(
          77              :                         '레인보우 - 볼링 클럽 매니저',
          78              :                         textAlign: TextAlign.center,
          79              :                         style: TextStyle(
          80              :                           fontSize: 24,
          81              :                           fontWeight: FontWeight.bold,
          82              :                           color: Colors.blue,
          83              :                         ),
          84              :                       ),
          85              :                     ],
          86              :                   ),
          87              :                   const SizedBox(height: 48),
          88              :
          89              :                   // 사용자명(아이디) 입력 필드
          90            1 :                   TextFormField(
          91            1 :                     controller: _usernameController,
          92              :                     decoration: const InputDecoration(
          93              :                       labelText: '아이디',
          94              :                       prefixIcon: Icon(Icons.person),
          95              :                       border: OutlineInputBorder(),
          96              :                     ),
          97            0 :                     validator: (value) {
          98            0 :                       if (value == null || value.isEmpty) {
          99              :                         return '아이디를 입력해주세요';
         100              :                       }
         101              :                       return null;
         102              :                     },
         103              :                   ),
         104              :                   const SizedBox(height: 16),
         105              :
         106              :                   // 비밀번호 입력 필드
         107            1 :                   TextFormField(
         108            1 :                     controller: _passwordController,
         109            1 :                     obscureText: !_isPasswordVisible,
         110            1 :                     decoration: InputDecoration(
         111              :                       labelText: '비밀번호',
         112              :                       prefixIcon: const Icon(Icons.lock),
         113              :                       border: const OutlineInputBorder(),
         114            1 :                       suffixIcon: IconButton(
         115            1 :                         icon: Icon(
         116            1 :                           _isPasswordVisible ? Icons.visibility : Icons.visibility_off,
         117              :                         ),
         118            0 :                         onPressed: () {
         119            0 :                           setState(() {
         120            0 :                             _isPasswordVisible = !_isPasswordVisible;
         121              :                           });
         122              :                         },
         123              :                       ),
         124              :                     ),
         125            0 :                     validator: (value) {
         126            0 :                       if (value == null || value.isEmpty) {
         127              :                         return '비밀번호를 입력해주세요';
         128              :                       }
         129              :                       return null;
         130              :                     },
         131              :                   ),
         132              :                   const SizedBox(height: 8),
         133              :
         134              :                   // 로그인 상태 유지 체크박스
         135            1 :                   Row(
         136            1 :                     children: [
         137            1 :                       Checkbox(
         138            1 :                         value: _rememberMe,
         139            0 :                         onChanged: (value) {
         140            0 :                           setState(() {
         141            0 :                             _rememberMe = value ?? false;
         142              :                           });
         143              :                         },
         144              :                       ),
         145              :                       const Text('로그인 상태 유지'),
         146              :                       const Spacer(),
         147            1 :                       TextButton(
         148            0 :                         onPressed: () {
         149            0 :                           Navigator.push(
         150              :                             context,
         151            0 :                             MaterialPageRoute(
         152            0 :                               builder: (context) => const ForgotPasswordScreen(),
         153              :                             ),
         154              :                           );
         155              :                         },
         156              :                         child: const Text('비밀번호 찾기'),
         157              :                       ),
         158              :                     ],
         159              :                   ),
         160              :                   const SizedBox(height: 24),
         161              :
         162              :                   // 로그인 버튼
         163            1 :                   ElevatedButton(
         164            2 :                     onPressed: authService.isLoading ? null : _login,
         165            1 :                     style: ElevatedButton.styleFrom(
         166              :                       padding: const EdgeInsets.symmetric(vertical: 16),
         167              :                       backgroundColor: Colors.blue,
         168              :                       foregroundColor: Colors.white,
         169              :                     ),
         170            1 :                     child: authService.isLoading
         171              :                         ? const SizedBox(
         172              :                             width: 20,
         173              :                             height: 20,
         174              :                             child: CircularProgressIndicator(
         175              :                               strokeWidth: 2,
         176              :                               color: Colors.white,
         177              :                             ),
         178              :                           )
         179              :                         : const Text(
         180              :                             '로그인',
         181              :                             style: TextStyle(fontSize: 16),
         182              :                           ),
         183              :                   ),
         184              :                   const SizedBox(height: 16),
         185              :
         186              :                   // 회원가입 링크
         187            1 :                   Row(
         188              :                     mainAxisAlignment: MainAxisAlignment.center,
         189            1 :                     children: [
         190              :                       const Text('계정이 없으신가요?'),
         191            1 :                       TextButton(
         192            0 :                         onPressed: () {
         193            0 :                           Navigator.push(
         194              :                             context,
         195            0 :                             MaterialPageRoute(
         196            0 :                               builder: (context) => const RegisterScreen(),
         197              :                             ),
         198              :                           );
         199              :                         },
         200              :                         child: const Text('회원가입'),
         201              :                       ),
         202              :                     ],
         203              :                   ),
         204              :                 ],
         205              :               ),
         206              :             ),
         207              :           ),
         208              :         ),
         209              :       ),
         210              :     );
         211              :   }
         212              : }

Generated by: LCOV version 2.3.1-1