Skip to content

Commit

Permalink
✨ [Feat] Generate Login & Term View (#25)
Browse files Browse the repository at this point in the history
* ✨[Feat] Main Login View

* ✨ [Feat] Generate Login & Term View

- 로그인 및 약관 화면 구현
- 백버튼 미적용
- 모두 동의 액션에 대한 의논 필요
  • Loading branch information
syss220211 authored Jun 19, 2024
1 parent 2b2ff8c commit 0d62aff
Show file tree
Hide file tree
Showing 19 changed files with 475 additions and 1 deletion.
79 changes: 79 additions & 0 deletions Projects/App/Sources/Presentation/Login/Main/LoginButton.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//
// LoginButton.swift
// App
//
// Created by 박서연 on 2024/06/18.
// Copyright © 2024 iOS. All rights reserved.
//

import SwiftUI
import DesignSystem

enum Login: String, CaseIterable {
case kakao
case apple

var image: Image {
switch self {
case .kakao:
return ZerosomeAsset.ic_kakako
case .apple:
return ZerosomeAsset.ic_apple
}
}

var backgroundColor: Color {
switch self {
case .kakao:
return Color.kakao
case .apple:
return Color.black
}
}

var titleColor: Color {
switch self {
case .kakao:
return Color.neutral800
case .apple:
return Color.white
}
}

var title: String {
switch self {
case .kakao:
"카카오 ID로 로그인"
case .apple:
"Apple ID로 로그인"
}
}
}

struct LoginButton: View {
let type: Login

init(type: Login) {
self.type = type
}

var body: some View {
HStack(spacing: 0) {
type.image
.frame(width: 24, height: 24)

Text(type.title)
.frame(maxWidth: .infinity, alignment: .center)
}
.padding(.init(top: 15, leading: 15, bottom: 15, trailing: 0))
.applyFont(font: .subtitle1)
.foregroundStyle(type.titleColor)
.background(type.backgroundColor)
.clipShape(RoundedRectangle(cornerRadius: 10))
}
}


#Preview {
LoginButton(type: .apple)
}
60 changes: 60 additions & 0 deletions Projects/App/Sources/Presentation/Login/Main/LoginView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//
// LoginView.swift
// App
//
// Created by 박서연 on 2024/06/18.
// Copyright © 2024 iOS. All rights reserved.
//

import SwiftUI
import Kingfisher
import DesignSystem



struct LoginView: View {
var body: some View {
ZStack {
Color.primaryFF6972
.ignoresSafeArea()

VStack {
ZerosomeAsset.zero_progress
.frame(width: 240, height: 240)
.clipShape(RoundedRectangle(cornerRadius: 40))

Spacer().frame(height: 123)

VStack(spacing: 12) {
ForEach(Login.allCases, id:\.self) { type in
LoginButton(type: type)
.onTapGesture {
switch type {
case .apple:
print("apple Login")
case .kakao:
print("kakao Login")
}
}
}
}
.padding(.horizontal, 24)
.padding(.bottom, 20)

VStack(spacing: 2) {
Text("일단 둘러볼게요")
.applyFont(font: .body2)
.foregroundStyle(Color.white)
.frame(maxWidth: .infinity, alignment: .center)

DivideRectangle(height: 1, color: .white)
.frame(width: 88)
}
}
}
}
}

#Preview {
LoginView()
}
48 changes: 48 additions & 0 deletions Projects/App/Sources/Presentation/Login/Term/SingleTermView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//
// SingleTermView.swift
// App
//
// Created by 박서연 on 2024/06/19.
// Copyright © 2024 iOS. All rights reserved.
//

import SwiftUI
import DesignSystem

struct SingleTermView: View {
@Binding var isChecked: Bool
var term: Term
var tapTitle: (Term) -> Void

var body: some View {
HStack(spacing: 12) {
(
isChecked
? ZerosomeAsset.ic_check_circle_primary
: ZerosomeAsset.ic_check_circle_gray
)
.resizable()
.frame(width: 24, height: 24)
.onTapGesture {
isChecked.toggle()
}

Text(term.title)
.applyFont(font: .body1)
.foregroundStyle(Color.neutral800)
.frame(maxWidth: .infinity, alignment: .leading)

Spacer()
Text("보기")
.applyFont(font: .body2)
.foregroundStyle(Color.neutral400)
.onTapGesture {
tapTitle(term)
}
}
}
}

#Preview {
SingleTermView(isChecked: .constant(true), term: .term, tapTitle: { _ in print("tapped")})
}
135 changes: 135 additions & 0 deletions Projects/App/Sources/Presentation/Login/Term/TermView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
//
// TermView.swift
// App
//
// Created by 박서연 on 2024/06/19.
// Copyright © 2024 iOS. All rights reserved.
//

import Combine
import DesignSystem
import SwiftUI

enum Term: CaseIterable{
case term
case personalInfo
case marketing

var title: String {
switch self {
case .term:
return "(필수) 서비스 이용약관 동의"
case .personalInfo:
return "(필수) 개인정보 처리방침 동의"
case .marketing:
return "(선택) 마케팅 수신 동의"
}
}
}

final class TermViewModel: ObservableObject {
@Published var isAllChecked: Bool = false
@Published var isTermChecked: Bool = false
@Published var isPersonalChecked: Bool = false
@Published var isMarketingChecked: Bool = false

private var cancellables = [AnyCancellable]()

init() {
Publishers.CombineLatest3($isTermChecked, $isPersonalChecked, $isMarketingChecked)
.sink { [weak self] term, personalInfo, marketing in
self?.isAllChecked = term && personalInfo || marketing
}
.store(in: &cancellables)
}

func toggleAll() {
if isTermChecked && isPersonalChecked && isMarketingChecked {
isTermChecked = false
isPersonalChecked = false
isMarketingChecked = false
} else {
isTermChecked = true
isPersonalChecked = true
isMarketingChecked = true
}
}
}

struct TermView: View {
@StateObject var viewModel = TermViewModel()
@State private var isTermChecked: Bool = false

var body: some View {
VStack(alignment:.leading, spacing: 30) {

VStack(alignment:.leading, spacing: 6) {
Text("약관에 동의해 주세요")
.applyFont(font: .heading1)
Text("여러분의 개인정보와 서비스 이용 권리\n잘 지켜드릴게요")
.applyFont(font: .body2)
.foregroundStyle(Color.neutral500)
}

VStack(alignment: .leading, spacing: 18) {
HStack(spacing: 12) {
(
viewModel.isAllChecked
? ZerosomeAsset.ic_check_circle_primary
: ZerosomeAsset.ic_check_circle_gray
)
.onTapGesture {
viewModel.toggleAll()
}

VStack(alignment:.leading, spacing: 2) {
Text("모두 동의")
.applyFont(font: .heading1)
Text("서비스 이용을 위해 아래 약관에 모두 동의합니다.")
.applyFont(font: .body2)
.foregroundStyle(Color.neutral500)
}
}

DivideRectangle(height: 1, color: Color.neutral100)
.padding(.bottom, 3)

SingleTermView(
isChecked: $viewModel.isTermChecked,
term: .term) { term in
print("이용약관 check")
}

SingleTermView(
isChecked: $viewModel.isPersonalChecked,
term: .personalInfo) { term in
print("개인정보 check")
}

SingleTermView(
isChecked: $viewModel.isMarketingChecked,
term: .marketing) { term in
print("마케팅 check")
}
}

Spacer()

CommonButton(title: "다음", font: .subtitle1)
.enable(viewModel.isAllChecked)
.tap {
print("button tapped..")
}
}
.padding(.horizontal, 22)
.navigationBackButton {

}
}
}

#Preview {
NavigationStack {
TermView()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

import SwiftUI
import DesignSystem

public extension View {
func navigationBackButton(_ action: @escaping () -> Void) -> some View {
Expand All @@ -16,7 +17,7 @@ public extension View {
Button(action: action, label: {
// TODO: - 백버튼 이미지 수정

Image("arrowBack")
ZerosomeAsset.ic_back_button
.resizable()
.frame(width: 24, height: 24)
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0.000",
"green" : "0.898",
"red" : "0.996"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "ic_apple.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "ic_kakao.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading

0 comments on commit 0d62aff

Please sign in to comment.