## 주요 변경사항 ### 아키텍처 개선 - Clean Architecture 패턴 적용 (Domain, Data, Presentation 레이어 분리) - Use Case 패턴 도입으로 비즈니스 로직 캡슐화 - Repository 패턴으로 데이터 접근 추상화 - 의존성 주입 구조 개선 ### 상태 관리 최적화 - 모든 Controller에서 불필요한 상태 관리 로직 제거 - 페이지네이션 로직 통일 및 간소화 - 에러 처리 로직 개선 (에러 메시지 한글화) - 로딩 상태 관리 최적화 ### Mock 서비스 제거 - MockDataService 완전 제거 - 모든 화면을 실제 API 전용으로 전환 - 불필요한 Mock 관련 코드 정리 ### UI/UX 개선 - Overview 화면 대시보드 기능 강화 - 라이선스 만료 알림 위젯 추가 - 사이드바 네비게이션 개선 - 일관된 UI 컴포넌트 사용 ### 코드 품질 - 중복 코드 제거 및 함수 추출 - 파일별 책임 분리 명확화 - 테스트 코드 업데이트 ## 영향 범위 - 모든 화면의 Controller 리팩토링 - API 통신 레이어 구조 개선 - 에러 처리 및 로깅 시스템 개선 ## 향후 계획 - 단위 테스트 커버리지 확대 - 통합 테스트 시나리오 추가 - 성능 모니터링 도구 통합
189 lines
5.7 KiB
Dart
189 lines
5.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
/// Metronic Admin 테일윈드 테마 (데모6 스타일)
|
|
class AppThemeTailwind {
|
|
// 메인 컬러 팔레트
|
|
static const Color primary = Color(0xFF5867DD);
|
|
static const Color secondary = Color(0xFF34BFA3);
|
|
static const Color success = Color(0xFF1BC5BD);
|
|
static const Color info = Color(0xFF8950FC);
|
|
static const Color warning = Color(0xFFFFA800);
|
|
static const Color danger = Color(0xFFF64E60);
|
|
static const Color light = Color(0xFFF3F6F9);
|
|
static const Color dark = Color(0xFF181C32);
|
|
static const Color muted = Color(0xFFB5B5C3);
|
|
|
|
// 배경 컬러
|
|
static const Color surface = Color(0xFFF7F8FA);
|
|
static const Color cardBackground = Colors.white;
|
|
|
|
// 테마 데이터
|
|
static ThemeData get lightTheme {
|
|
return ThemeData(
|
|
primaryColor: primary,
|
|
colorScheme: const ColorScheme.light(
|
|
primary: primary,
|
|
secondary: secondary,
|
|
surface: surface,
|
|
error: danger,
|
|
),
|
|
scaffoldBackgroundColor: surface,
|
|
fontFamily: 'Poppins',
|
|
|
|
// AppBar 테마
|
|
appBarTheme: const AppBarTheme(
|
|
backgroundColor: Colors.white,
|
|
foregroundColor: dark,
|
|
elevation: 0,
|
|
centerTitle: false,
|
|
titleTextStyle: TextStyle(
|
|
color: dark,
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
iconTheme: IconThemeData(color: dark),
|
|
),
|
|
|
|
// 버튼 테마
|
|
elevatedButtonTheme: ElevatedButtonThemeData(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: primary,
|
|
foregroundColor: Colors.white,
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
|
|
),
|
|
),
|
|
|
|
// 카드 테마
|
|
cardTheme: CardThemeData(
|
|
color: Colors.white,
|
|
elevation: 1,
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
|
margin: const EdgeInsets.symmetric(vertical: 8),
|
|
),
|
|
|
|
// 입력 폼 테마
|
|
inputDecorationTheme: InputDecorationTheme(
|
|
filled: true,
|
|
fillColor: Colors.white,
|
|
contentPadding: const EdgeInsets.symmetric(
|
|
horizontal: 16,
|
|
vertical: 12,
|
|
),
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(6),
|
|
borderSide: const BorderSide(color: Color(0xFFE5E7EB)),
|
|
),
|
|
enabledBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(6),
|
|
borderSide: const BorderSide(color: Color(0xFFE5E7EB)),
|
|
),
|
|
focusedBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(6),
|
|
borderSide: const BorderSide(color: primary),
|
|
),
|
|
errorBorder: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(6),
|
|
borderSide: const BorderSide(color: danger),
|
|
),
|
|
floatingLabelBehavior: FloatingLabelBehavior.never,
|
|
),
|
|
|
|
// 데이터 테이블 테마
|
|
dataTableTheme: const DataTableThemeData(
|
|
headingRowColor: WidgetStatePropertyAll(light),
|
|
dividerThickness: 1,
|
|
columnSpacing: 24,
|
|
headingTextStyle: TextStyle(
|
|
color: dark,
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 14,
|
|
),
|
|
dataTextStyle: TextStyle(color: Color(0xFF6C7293), fontSize: 14),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 스타일 - 헤딩 및 텍스트
|
|
static const TextStyle headingStyle = TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.bold,
|
|
color: dark,
|
|
);
|
|
|
|
static const TextStyle subheadingStyle = TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w600,
|
|
color: dark,
|
|
);
|
|
|
|
static const TextStyle bodyStyle = TextStyle(
|
|
fontSize: 14,
|
|
color: Color(0xFF6C7293),
|
|
);
|
|
|
|
// 굵은 본문 텍스트
|
|
static const TextStyle bodyBoldStyle = TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w600,
|
|
color: dark,
|
|
);
|
|
|
|
static const TextStyle smallText = TextStyle(fontSize: 12, color: muted);
|
|
|
|
// 버튼 스타일
|
|
static final ButtonStyle primaryButtonStyle = ElevatedButton.styleFrom(
|
|
backgroundColor: primary,
|
|
foregroundColor: Colors.white,
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
|
|
);
|
|
|
|
// 라벨 스타일
|
|
static const TextStyle formLabelStyle = TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w600,
|
|
color: dark,
|
|
);
|
|
|
|
static final ButtonStyle secondaryButtonStyle = ElevatedButton.styleFrom(
|
|
backgroundColor: secondary,
|
|
foregroundColor: Colors.white,
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
|
|
);
|
|
|
|
static final ButtonStyle outlineButtonStyle = OutlinedButton.styleFrom(
|
|
foregroundColor: primary,
|
|
side: const BorderSide(color: primary),
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
|
|
);
|
|
|
|
// 카드 장식
|
|
static final BoxDecoration cardDecoration = BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(8),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withAlpha(13),
|
|
blurRadius: 10,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
],
|
|
);
|
|
|
|
// 기타 장식
|
|
static final BoxDecoration containerDecoration = BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(8),
|
|
border: Border.all(color: const Color(0xFFE5E7EB)),
|
|
);
|
|
|
|
static const EdgeInsets cardPadding = EdgeInsets.all(20);
|
|
static const EdgeInsets listPadding = EdgeInsets.symmetric(
|
|
vertical: 8,
|
|
horizontal: 16,
|
|
);
|
|
}
|