초기 커밋

This commit is contained in:
2026-03-01 07:55:59 +09:00
commit b0262d6bab
67 changed files with 4660 additions and 0 deletions

36
lib/app/app.dart Normal file
View File

@@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:responsive_framework/responsive_framework.dart';
import '../core/router/app_router.dart';
import 'app_providers.dart';
import 'theme/app_theme.dart';
/// 앱 루트 위젯
class App extends ConsumerWidget {
const App({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final router = ref.watch(appRouterProvider);
final themeMode = ref.watch(themeModeNotifierProvider);
return MaterialApp.router(
title: 'Flutter Frame',
debugShowCheckedModeBanner: false,
theme: AppTheme.light,
darkTheme: AppTheme.dark,
themeMode: themeMode,
routerConfig: router,
builder: (context, child) => ResponsiveBreakpoints.builder(
child: child!,
breakpoints: const [
Breakpoint(start: 0, end: 450, name: MOBILE),
Breakpoint(start: 451, end: 800, name: TABLET),
Breakpoint(start: 801, end: 1920, name: DESKTOP),
Breakpoint(start: 1921, end: double.infinity, name: '4K'),
],
),
);
}
}

View File

@@ -0,0 +1,24 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'app_providers.g.dart';
/// 테마 모드 상태 관리
@riverpod
class ThemeModeNotifier extends _$ThemeModeNotifier {
@override
ThemeMode build() => ThemeMode.system;
void setThemeMode(ThemeMode mode) {
state = mode;
}
void toggleTheme() {
state = switch (state) {
ThemeMode.light => ThemeMode.dark,
ThemeMode.dark => ThemeMode.light,
ThemeMode.system => ThemeMode.dark,
};
}
}

View File

@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
/// 앱 커스텀 컬러 상수
abstract final class AppColors {
// Primary
static const Color primary = Color(0xFF1E40AF);
static const Color primaryLight = Color(0xFF3B82F6);
static const Color primaryDark = Color(0xFF1E3A8A);
// Secondary
static const Color secondary = Color(0xFF7C3AED);
static const Color secondaryLight = Color(0xFF8B5CF6);
static const Color secondaryDark = Color(0xFF6D28D9);
// Status
static const Color success = Color(0xFF16A34A);
static const Color warning = Color(0xFFEAB308);
static const Color error = Color(0xFFDC2626);
static const Color info = Color(0xFF0EA5E9);
// Neutral
static const Color background = Color(0xFFF8FAFC);
static const Color surface = Color(0xFFFFFFFF);
static const Color textPrimary = Color(0xFF0F172A);
static const Color textSecondary = Color(0xFF64748B);
static const Color border = Color(0xFFE2E8F0);
static const Color divider = Color(0xFFF1F5F9);
// Dark Mode
static const Color darkBackground = Color(0xFF0F172A);
static const Color darkSurface = Color(0xFF1E293B);
static const Color darkTextPrimary = Color(0xFFF8FAFC);
static const Color darkTextSecondary = Color(0xFF94A3B8);
static const Color darkBorder = Color(0xFF334155);
}

View File

@@ -0,0 +1,62 @@
import 'package:flex_color_scheme/flex_color_scheme.dart';
import 'package:flutter/material.dart';
/// FlexColorScheme 기반 라이트/다크 테마 설정
abstract final class AppTheme {
/// 라이트 테마
static ThemeData get light => FlexThemeData.light(
scheme: FlexScheme.indigo,
surfaceMode: FlexSurfaceMode.levelSurfacesLowScaffold,
blendLevel: 7,
subThemesData: const FlexSubThemesData(
blendOnLevel: 10,
blendOnColors: false,
useTextTheme: true,
useM2StyleDividerInM3: true,
alignedDropdown: true,
useInputDecoratorThemeInDialogs: true,
inputDecoratorBorderType: FlexInputBorderType.outline,
inputDecoratorRadius: 8,
chipRadius: 8,
cardRadius: 12,
dialogRadius: 16,
bottomSheetRadius: 16,
elevatedButtonRadius: 8,
outlinedButtonRadius: 8,
filledButtonRadius: 8,
textButtonRadius: 8,
fabRadius: 16,
),
visualDensity: FlexColorScheme.comfortablePlatformDensity,
useMaterial3: true,
fontFamily: 'Pretendard',
);
/// 다크 테마
static ThemeData get dark => FlexThemeData.dark(
scheme: FlexScheme.indigo,
surfaceMode: FlexSurfaceMode.levelSurfacesLowScaffold,
blendLevel: 13,
subThemesData: const FlexSubThemesData(
blendOnLevel: 20,
useTextTheme: true,
useM2StyleDividerInM3: true,
alignedDropdown: true,
useInputDecoratorThemeInDialogs: true,
inputDecoratorBorderType: FlexInputBorderType.outline,
inputDecoratorRadius: 8,
chipRadius: 8,
cardRadius: 12,
dialogRadius: 16,
bottomSheetRadius: 16,
elevatedButtonRadius: 8,
outlinedButtonRadius: 8,
filledButtonRadius: 8,
textButtonRadius: 8,
fabRadius: 16,
),
visualDensity: FlexColorScheme.comfortablePlatformDensity,
useMaterial3: true,
fontFamily: 'Pretendard',
);
}