Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
68EC1B2C1A3B218FDF0EFCB0 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6FA4738BD42C2EA3B04828C7 /* Pods_RunnerTests.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
85F5290E78FB927A6A4151B7 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E179CE21DC206336C82F2D4F /* Pods_RunnerTests.framework */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
Expand Down Expand Up @@ -42,15 +43,20 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
0E76FD0723FCBCB2F66DD66B /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
1ED101AAD75DBC7A1CC7DB01 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
37A1BEE63A453422AECDCFEE /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
384964D6DA813F8D7A6F18CB /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
61FA2A96D4181BA172C28931 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7BBBD328FF90A984C92A61A3 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
9748F6C9ED5A207C4270A1DC /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
Expand All @@ -68,6 +74,14 @@
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
80C56BE658C7A12CAD32F5A7 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
68EC1B2C1A3B218FDF0EFCB0 /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
Expand Down
32 changes: 31 additions & 1 deletion lib/common/design_system/app_colors.dart
Original file line number Diff line number Diff line change
@@ -1,30 +1,44 @@
import 'package:flutter/material.dart';

abstract class AppColors {
// Color groups
static const gray = _Gray();
static const primary = _Primary();
static const pink = _Pink();
static const violet = _Violet();

// Basic
static const white = Color(0xFFFFFFFF);
static const black = Color(0xFF000000);

// Semantic
// Text
static const textPrimary = Color(0xFF101828);
static const textSecondary = Color(0xFF6A7282);
static const textTertiary = Color(0xFF364153);
static const textDisabled = Color(0xFF98A2B3);
static const textOnDark = white;

// Background
static const backgroundPrimary = white;
static const backgroundSecondary = Color(0xFFF9FAFB);
static const backgroundInverse = Color(0xFF101828);
static const backgroundVioletLight = Color(0xFFEEF2FF);

// Border
static const borderPrimary = Color(0xFFE5E7EB);
static const borderSecondary = Color(0xFFF3F4F6);
static const divider = Color(0xFFF3F4F6);

// Brand
static const brandPrimary = Color(0xFF2563EB);
static const brandPrimaryPressed = Color(0xFF1D4ED8);
static const brandPrimaryLight = Color(0xFFEFF6FF);
static const brandAccent = Color(0xFF2B7FFF);

// Semantic
static const error = Color(0xFFFB2C36);
static const infoTitle = Color(0xFF1C398E);
static const infoBody = Color(0xFF1447E6);

// App specific
static const loginGradientTop = Color.fromARGB(255, 121, 195, 255);
Expand Down Expand Up @@ -58,3 +72,19 @@ class _Primary {
final Color t600 = const Color(0xFF2563EB);
final Color t700 = const Color(0xFF1D4ED8);
}

class _Pink {
const _Pink();

final Color t400 = const Color(0xFFF6339A);
final Color t500 = const Color(0xFFE60076);
final Color t600 = const Color(0xFFEC003F);
}

class _Violet {
const _Violet();

final Color t400 = const Color(0xFF615FFF);
final Color t500 = const Color(0xFF4F39F6);
final Color t600 = const Color(0xFF9810FA);
}
36 changes: 36 additions & 0 deletions lib/common/design_system/app_text_styles.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'package:flutter/material.dart';

abstract class AppTextStyles {
static const display = _Scale(fontSize: 36, letterSpacing: 0.37);
static const heading1 = _Scale(fontSize: 30, letterSpacing: 0.40, height: 1.2);
static const heading2 = _Scale(fontSize: 24, letterSpacing: 0.07, height: 1.33);
static const heading3 = _Scale(fontSize: 20, letterSpacing: -0.45, height: 1.4);
static const title = _Scale(fontSize: 18, letterSpacing: -0.44, height: 1.56);
static const body = _Scale(fontSize: 16, letterSpacing: -0.31, height: 1.5);
static const label = _Scale(fontSize: 14, letterSpacing: -0.15, height: 1.43);
static const caption = _Scale(fontSize: 12, height: 1.33);
}

class _Scale {
final double fontSize;
final double? letterSpacing;
final double? height;

const _Scale({
required this.fontSize,
this.letterSpacing,
this.height,
});

TextStyle get bold => _build(FontWeight.bold);
TextStyle get semibold => _build(FontWeight.w600);
TextStyle get medium => _build(FontWeight.w500);
TextStyle get regular => _build(FontWeight.w400);

TextStyle _build(FontWeight weight) => TextStyle(
fontSize: fontSize,
fontWeight: weight,
letterSpacing: letterSpacing,
height: height,
);
}
11 changes: 6 additions & 5 deletions lib/common/views/logo.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:yuktoe/common/design_system/app_colors.dart';

class Logo extends StatelessWidget {
const Logo({super.key});
Expand All @@ -10,26 +11,26 @@ class Logo extends StatelessWidget {
height: 112,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24),
gradient: const LinearGradient(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Color(0xFF2B7FFF), Color(0xFF4F39F6)],
colors: [AppColors.brandAccent, AppColors.violet.t500],
),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.1),
color: AppColors.black.withValues(alpha: 0.1),
blurRadius: 25,
offset: const Offset(0, 20),
),
BoxShadow(
color: Colors.black.withValues(alpha: 0.1),
color: AppColors.black.withValues(alpha: 0.1),
blurRadius: 10,
offset: const Offset(0, 8),
),
],
),
child: const Center(
child: Icon(Icons.child_care, size: 64, color: Colors.white),
child: Icon(Icons.child_care, size: 64, color: AppColors.textOnDark),
),
);
}
Expand Down
69 changes: 69 additions & 0 deletions lib/constants/app_strings.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
abstract final class AppStrings {
// Common
static const next = '다음으로';
static const confirm = '확인';
static const cancel = '취소';
static const done = '완료';
static const yes = '맞아요';
static const no = '아니요';
static const termsOfService = '서비스 이용약관';
static const privacyPolicy = '개인정보 처리방침';
static const termsAgreeSuffix = '에 동의합니다 ';
static const requiredMark = '*';
static const birthDate = '생년월일';
static const maleLabel = '남자 아기';
static const femaleLabel = '여자 아기';
static const genericError = '오류가 발생했습니다.';

// Login
static const appTitle = '내꿈은육퇴';
static const appSubtitle = '우리 아기 성장 기록';
static const kakaoLogin = '카카오로 시작하기';
static const googleLogin = 'Google로 시작하기';
static const appleLogin = 'Apple로 시작하기';

// Welcome
static const welcomeTitle = '환영합니다!';
static const welcomeSubtitle = '시작 방법을 선택해주세요';
static const welcomeFooter = '가족 구성원과 함께 아기의 성장을 기록하고 공유하세요';
static const registerBabyTitle = '우리 아기 등록하기';
static const registerBabyDescription = '새로운 아기의 정보를 등록합니다';
static const inviteCodeTitle = '초대 코드가 있어요';
static const inviteCodeDescription = '가족 초대 코드로 참여합니다';

// Baby Registration
static const babyRegistrationAppBar = '우리 아기 등록';
static const nameLabel = '이름';
static const nameHint = '아기 이름을 입력하세요';
static const genderLabel = '성별';
static const dueDateLabel = '출산 예정일';

// Invite Code
static const inviteCodeAppBar = '초대 코드 입력';
static const inviteCodeHeading = '가족 초대 코드를 입력하세요';
static const inviteCodeSubheading =
'가족 구성원으로부터 받은 초대 코드를 입력하면\n아기 정보를 함께 공유할 수 있어요';
static const inviteCodeFieldLabel = '초대 코드 ';
static const inviteCodeHint = '예: ABC-123-XYZ';
static const inviteCodeHelp = '대시(-)를 포함하여 입력하세요';
static const inviteCodeInfoTitle = '초대 코드는 어디서 받나요?';
static const inviteCodeInfoBody =
'이미 등록된 가족 구성원의 설정 메뉴에서\n\'가족 초대하기\'를 통해 코드를 받을 수 있습니다.';
static const babyNotFoundTitle = '아기를 찾을 수 없어요';
static const babyNotFoundBody =
'입력한 초대 코드와 일치하는 아기가 없습니다.\n코드를 다시 확인해주세요.';
static const babyConfirmTitle = '이 아기가 맞나요?';

// Baby Profile Setup
static const profileSetupHeading = '거의 다 왔어요!';
static const profileSetupSubheading = '마지막으로 정보를 입력해주세요';
static const relationshipLabel = '아기와의 관계';
static const relationshipMom = '엄마';
static const relationshipDad = '아빠';
static const relationshipFamily = '가족';
static const relationshipOther = '기타';
static const nicknameLabel = '닉네임';
static const nicknameHint = '예: 리암엄마';
static const nicknameHelper = '다른 가족 구성원에게 표시될 이름이에요';
static const start = '시작하기';
}
7 changes: 7 additions & 0 deletions lib/constants/enum/gender.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
enum Gender {
male('male'),
female('female');

const Gender(this.serverValue);
final String serverValue;
}
9 changes: 9 additions & 0 deletions lib/constants/enum/relationship.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
enum Relationship {
mom('mom'),
dad('dad'),
family('family'),
other('other');

const Relationship(this.serverValue);
final String serverValue;
}
14 changes: 14 additions & 0 deletions lib/core/config/dependencies.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:yuktoe/core/config/app_env.dart';
import 'package:yuktoe/data/repositories/auth_repository/auth_repository.dart';
import 'package:yuktoe/data/repositories/auth_repository/auth_repository_impl.dart';
import 'package:yuktoe/data/repositories/baby_registration_repository/baby_registration_repository.dart';
import 'package:yuktoe/data/repositories/baby_registration_repository/baby_registration_repository_impl.dart';
import 'package:yuktoe/data/services/auth_service/auth_service.dart';
import 'package:yuktoe/data/services/auth_service/supabase_auth_service.dart';
import 'package:yuktoe/data/services/baby_registration_service/baby_registration_service.dart';
import 'package:yuktoe/data/services/baby_registration_service/supabase_baby_registration_service.dart';

List<SingleChildWidget> buildDependencies() {
return [
Expand All @@ -19,5 +23,15 @@ List<SingleChildWidget> buildDependencies() {
Provider<AuthRepository>(
create: (context) => AuthRepositoryImpl(context.read<AuthService>()),
),
Provider<BabyRegistrationService>(
create: (context) => SupabaseBabyRegistrationService(
client: context.read<SupabaseClient>(),
),
),
Provider<BabyRegistrationRepository>(
create: (context) => BabyRegistrationRepositoryImpl(
context.read<BabyRegistrationService>(),
),
),
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:yuktoe/domain/models/baby_registration/baby_summary.dart';

abstract interface class BabyRegistrationRepository {
Future<String> createBaby({
required String name,
String? birthDate,
String? dueDate,
required String gender,
required String relationship,
required String nickname,
});

Future<BabySummary?> verifyInviteCode(String code);

Future<String> joinBabyByInviteCode({
required String code,
required String relationship,
required String nickname,
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import 'package:yuktoe/core/result.dart';
import 'package:yuktoe/data/repositories/baby_registration_repository/baby_registration_repository.dart';
import 'package:yuktoe/data/services/baby_registration_service/baby_registration_service.dart';
import 'package:yuktoe/domain/models/baby_registration/baby_summary.dart';

class BabyRegistrationRepositoryImpl implements BabyRegistrationRepository {
final BabyRegistrationService _service;

BabyRegistrationRepositoryImpl(this._service);

@override
Future<String> createBaby({
required String name,
String? birthDate,
String? dueDate,
required String gender,
required String relationship,
required String nickname,
}) async {
final result = await _service.createBaby(
name: name,
birthDate: birthDate,
dueDate: dueDate,
gender: gender,
relationship: relationship,
nickname: nickname,
);

switch (result) {
case Ok<String>():
return result.value;
case Error<String>():
throw result.error;
}
}

@override
Future<BabySummary?> verifyInviteCode(String code) async {
final result = await _service.verifyInviteCode(code);

switch (result) {
case Ok<BabySummary?>():
return result.value;
case Error<BabySummary?>():
throw result.error;
}
}

@override
Future<String> joinBabyByInviteCode({
required String code,
required String relationship,
required String nickname,
}) async {
final result = await _service.joinBabyByInviteCode(
code: code,
relationship: relationship,
nickname: nickname,
);

switch (result) {
case Ok<String>():
return result.value;
case Error<String>():
throw result.error;
}
}
}
Loading