로그인 · 회원가입 흐름을 서버 계정·약관 동의와 연결
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../core/firebase/firebase_boot.dart';
|
||||
import '../../core/i18n/app_locale.dart';
|
||||
import '../../core/theme/tokens.dart';
|
||||
import '../../core/ui/app_icons.dart';
|
||||
import 'auth.dart';
|
||||
@@ -62,14 +63,14 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_busy = false;
|
||||
_notice = authNotice(outcome);
|
||||
_notice = authNotice(outcome, context.l10n);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _resetPassword() async {
|
||||
final email = _email.text.trim();
|
||||
if (email.isEmpty) {
|
||||
setState(() => _notice = '재설정 메일을 받으실 이메일을 먼저 입력해 주세요.');
|
||||
setState(() => _notice = context.l10n.authResetNeedEmail);
|
||||
return;
|
||||
}
|
||||
final impl = widget.auth.qaEmailProvider;
|
||||
@@ -81,8 +82,8 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
_busy = false;
|
||||
// 성공해도 계정 존재 여부를 알려 주지 않는다. 가입된 이메일을 훑을 수 있다.
|
||||
_notice = outcome is AuthFailed
|
||||
? authNotice(outcome)
|
||||
: '입력하신 주소로 재설정 안내를 보냈습니다.';
|
||||
? authNotice(outcome, context.l10n)
|
||||
: context.l10n.authResetSent;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -171,12 +172,12 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
backgroundColor: AppColors.cosmicAccent,
|
||||
foregroundColor: AppColors.onCosmicAccent,
|
||||
),
|
||||
child: const Text('로그인'),
|
||||
child: Text(context.l10n.authLogin),
|
||||
),
|
||||
const SizedBox(height: AppSpace.s4),
|
||||
AuthSwitchRow(
|
||||
question: '팬우주는 처음이세요?',
|
||||
action: '회원가입',
|
||||
question: context.l10n.authFirstTime,
|
||||
action: context.l10n.authSignup,
|
||||
onTap: () => _open(signUp: true),
|
||||
),
|
||||
],
|
||||
@@ -216,7 +217,7 @@ class _SimpleLoginScreenState extends State<SimpleLoginScreen> {
|
||||
if (agreed != true || !mounted) return;
|
||||
}
|
||||
setState(() => _busy = true);
|
||||
final outcome = await widget.auth.signIn(provider);
|
||||
final outcome = await widget.auth.signIn(provider, signUp: widget.signUp);
|
||||
if (!mounted) return;
|
||||
setState(() => _busy = false);
|
||||
// 키 대기 제공자는 안내 다이얼로그로 끊는다 — 눌렀는데 아무 일도 안 일어나면
|
||||
@@ -226,7 +227,7 @@ class _SimpleLoginScreenState extends State<SimpleLoginScreen> {
|
||||
return;
|
||||
}
|
||||
if (!mounted) return;
|
||||
setState(() => _notice = authNotice(outcome));
|
||||
setState(() => _notice = authNotice(outcome, context.l10n));
|
||||
}
|
||||
|
||||
Future<void> _showNotConfigured(AuthNotConfigured outcome) async {
|
||||
@@ -234,15 +235,17 @@ class _SimpleLoginScreenState extends State<SimpleLoginScreen> {
|
||||
await showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text('$name 로그인 준비 중'),
|
||||
title: Text(context.l10n.authNotConfiguredTitle(name)),
|
||||
content: Text(
|
||||
'$name 로그인은 발주사 키가 들어오면 열립니다.\n\n'
|
||||
'필요한 항목\n· ${outcome.missing.join('\n· ')}',
|
||||
context.l10n.authNotConfiguredBody(
|
||||
name,
|
||||
outcome.missing.join('\n· '),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('확인'),
|
||||
child: Text(context.l10n.commonConfirm),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -294,8 +297,8 @@ class _SimpleLoginScreenState extends State<SimpleLoginScreen> {
|
||||
const SizedBox(height: AppSpace.s5),
|
||||
Text(
|
||||
signUp
|
||||
? '가장 편한 방법으로\n팬우주에 회원가입 하세요!'
|
||||
: '가장 편한 방법으로\n팬우주에 로그인하세요!',
|
||||
? context.l10n.authSignupHeadline
|
||||
: context.l10n.authLoginHeadline,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontFamily: AppFonts.body,
|
||||
@@ -317,7 +320,11 @@ class _SimpleLoginScreenState extends State<SimpleLoginScreen> {
|
||||
for (final p in providers) ...[
|
||||
_ProviderButton(
|
||||
provider: p.provider,
|
||||
label: providerButtonLabel(p.provider, signUp: signUp),
|
||||
label: providerButtonLabel(
|
||||
p.provider,
|
||||
signUp: signUp,
|
||||
l10n: context.l10n,
|
||||
),
|
||||
enabled: !_busy,
|
||||
onPressed: () => _signIn(p.provider),
|
||||
),
|
||||
@@ -329,13 +336,13 @@ class _SimpleLoginScreenState extends State<SimpleLoginScreen> {
|
||||
],
|
||||
signUp
|
||||
? AuthSwitchRow(
|
||||
question: '이미 가입하셨나요?',
|
||||
action: '로그인',
|
||||
question: context.l10n.authAlreadyMember,
|
||||
action: context.l10n.authLogin,
|
||||
onTap: _switchMode,
|
||||
)
|
||||
: AuthSwitchRow(
|
||||
question: '팬우주는 처음이세요?',
|
||||
action: '회원가입',
|
||||
question: context.l10n.authFirstTime,
|
||||
action: context.l10n.authSignup,
|
||||
onTap: _switchMode,
|
||||
),
|
||||
],
|
||||
@@ -357,26 +364,29 @@ const _figmaOrder = [
|
||||
|
||||
/// 간편 로그인 · 회원가입 버튼 문구 — 시안 「Kakao로 로그인」 · 「Kakao로 가입하기」.
|
||||
/// [AuthProviderKind.label](「카카오로 시작하기」)은 설정 · 안내 문구가 쓰므로 따로 둔다.
|
||||
String providerButtonLabel(AuthProviderKind kind, {bool signUp = false}) =>
|
||||
'${_names[kind]} ${signUp ? '가입하기' : '로그인'}';
|
||||
/// 제공자별 조사(ko 「LINE으로」)는 arb 의 select 가 맡는다. [l10n] 이 없으면 ko.
|
||||
String providerButtonLabel(
|
||||
AuthProviderKind kind, {
|
||||
bool signUp = false,
|
||||
AppLocalizations? l10n,
|
||||
}) {
|
||||
final t = l10n ?? koL10n;
|
||||
return signUp
|
||||
? t.authProviderSignup(kind.name)
|
||||
: t.authProviderLogin(kind.name);
|
||||
}
|
||||
|
||||
/// 시안 버튼 문구의 제공자 표기. LINE 은 조사가 「으로」다.
|
||||
const _names = {
|
||||
AuthProviderKind.apple: 'Apple로',
|
||||
AuthProviderKind.google: 'Google로',
|
||||
AuthProviderKind.kakao: 'Kakao로',
|
||||
AuthProviderKind.line: 'LINE으로',
|
||||
AuthProviderKind.email: '이메일로',
|
||||
};
|
||||
|
||||
String? authNotice(AuthOutcome outcome) => switch (outcome) {
|
||||
AuthSucceeded() => null,
|
||||
AuthCancelled() => null,
|
||||
AuthFailed(:final code, :final message) => '[$code] $message',
|
||||
AuthNotConfigured(:final provider, :final missing) =>
|
||||
'${provider.shortName} 로그인은 아직 준비 중입니다.\n'
|
||||
'필요한 항목: ${missing.join(' · ')}',
|
||||
};
|
||||
String? authNotice(AuthOutcome outcome, [AppLocalizations? l10n]) =>
|
||||
switch (outcome) {
|
||||
AuthSucceeded() => null,
|
||||
AuthCancelled() => null,
|
||||
AuthFailed(:final code, :final message) => '[$code] $message',
|
||||
AuthNotConfigured(:final provider, :final missing) =>
|
||||
(l10n ?? koL10n).authNotConfiguredNotice(
|
||||
provider.shortName,
|
||||
missing.join(' · '),
|
||||
),
|
||||
};
|
||||
|
||||
TextStyle _abz(double size, Color color) => TextStyle(
|
||||
fontFamily: AppFonts.display,
|
||||
|
||||
Reference in New Issue
Block a user