Skip to content
Open
9 changes: 9 additions & 0 deletions Domain/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
28 changes: 28 additions & 0 deletions Domain/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// swift-tools-version: 5.7
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "Domain",
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "Domain",
targets: ["Domain"])
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "Domain",
dependencies: []),
.testTarget(
name: "DomainTests",
dependencies: ["Domain"])
]
)
3 changes: 3 additions & 0 deletions Domain/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Domain

A description of this package.
9 changes: 9 additions & 0 deletions Domain/Sources/Domain/Entities/User.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
public struct User {
public let email: String
public let tokenID: String

public init(email: String, tokenID: String) {
self.email = email
self.tokenID = tokenID
}
}
4 changes: 4 additions & 0 deletions Domain/Sources/Domain/UseCases/LoginUseCase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@available(iOS 13.0.0, *)
public protocol LoginUseCase {
func login(email: String, password: String) async throws -> User
}
4 changes: 4 additions & 0 deletions Domain/Sources/Domain/UseCases/RegisterUseCase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@available(iOS 13.0.0, *)
public protocol RegisterUseCase {
func register(email: String, password: String) async throws -> User
}
10 changes: 10 additions & 0 deletions Domain/Tests/DomainTests/DomainTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import XCTest
@testable import Domain

final class DomainTests: XCTestCase {
func testExample() throws {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct
// results.
}
}
48 changes: 44 additions & 4 deletions Healthy.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
025511D42A3D0A8B00295B91 /* CreateAccountViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025511CC2A3D0A8B00295B91 /* CreateAccountViewModel.swift */; };
025511D52A3D0A8B00295B91 /* CreateAccountviewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025511CD2A3D0A8B00295B91 /* CreateAccountviewModelType.swift */; };
025511D62A3D0A8B00295B91 /* CreateAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025511CE2A3D0A8B00295B91 /* CreateAccountViewController.swift */; };
02557D712A697DF90022756A /* LoginUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02557D702A697DF90022756A /* LoginUseCase.swift */; };
02557D732A697E8E0022756A /* Domain in Frameworks */ = {isa = PBXBuildFile; productRef = 02557D722A697E8E0022756A /* Domain */; };
025A47532A336B05008BF85A /* DashboardViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025A474F2A336B05008BF85A /* DashboardViewModelType.swift */; };
025A47542A336B05008BF85A /* DashboardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025A47502A336B05008BF85A /* DashboardViewController.swift */; };
025A47552A336B05008BF85A /* DashboardViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 025A47512A336B05008BF85A /* DashboardViewModel.swift */; };
Expand Down Expand Up @@ -68,6 +70,7 @@
0296F7932A4342B500DBC86A /* FacebookCore in Frameworks */ = {isa = PBXBuildFile; productRef = 0296F7922A4342B500DBC86A /* FacebookCore */; };
0296F7952A4342B500DBC86A /* FacebookLogin in Frameworks */ = {isa = PBXBuildFile; productRef = 0296F7942A4342B500DBC86A /* FacebookLogin */; };
0296F7972A43491B00DBC86A /* FacebookAuthenticator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0296F7962A43491B00DBC86A /* FacebookAuthenticator.swift */; };
02CB9B642A6ADE4E00C1E765 /* DefaultLoginUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CB9B632A6ADE4E00C1E765 /* DefaultLoginUseCaseTests.swift */; };
02EEC3FB2A4C22C90007DA0C /* SavedRecipesViewModelMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02EEC3FA2A4C22C90007DA0C /* SavedRecipesViewModelMock.swift */; };
02EEC3FD2A4C23090007DA0C /* SavedRecipesViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02EEC3FC2A4C23090007DA0C /* SavedRecipesViewControllerTests.swift */; };
02EEC3FF2A4C244A0007DA0C /* SavedRecipesViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02EEC3FE2A4C244A0007DA0C /* SavedRecipesViewModelTests.swift */; };
Expand Down Expand Up @@ -111,6 +114,8 @@
79311FD82A19214700764707 /* UITextField+Style.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79311FD72A19214700764707 /* UITextField+Style.swift */; };
798B59B22A5D15E600E4DCFF /* MealCategories.swift in Sources */ = {isa = PBXBuildFile; fileRef = 798B59B12A5D15E600E4DCFF /* MealCategories.swift */; };
79B65D282A0FB4310042CC46 /* UIButton+Style.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79B65D272A0FB4310042CC46 /* UIButton+Style.swift */; };
79FC924F2A704DC30001F255 /* RegisterUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FC924E2A704DC30001F255 /* RegisterUseCase.swift */; };
79FC92512A705BE80001F255 /* DefaultRegisterUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79FC92502A705BE80001F255 /* DefaultRegisterUseCaseTests.swift */; };
A21C51F92A42FF8D00850B15 /* SavedRecipesTableViewCellTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A21C51F82A42FF8D00850B15 /* SavedRecipesTableViewCellTests.swift */; };
A21C51FB2A43036A00850B15 /* UITableViewMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = A21C51FA2A43036A00850B15 /* UITableViewMock.swift */; };
A27861152A445E8E00BA7018 /* UITableView+RegisterNib.swift in Sources */ = {isa = PBXBuildFile; fileRef = A27861142A445E8E00BA7018 /* UITableView+RegisterNib.swift */; };
Expand Down Expand Up @@ -193,6 +198,8 @@
025511CC2A3D0A8B00295B91 /* CreateAccountViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateAccountViewModel.swift; sourceTree = "<group>"; };
025511CD2A3D0A8B00295B91 /* CreateAccountviewModelType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateAccountviewModelType.swift; sourceTree = "<group>"; };
025511CE2A3D0A8B00295B91 /* CreateAccountViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateAccountViewController.swift; sourceTree = "<group>"; };
02557D6E2A697C3D0022756A /* Domain */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Domain; sourceTree = "<group>"; };
02557D702A697DF90022756A /* LoginUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginUseCase.swift; sourceTree = "<group>"; };
025A474F2A336B05008BF85A /* DashboardViewModelType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardViewModelType.swift; sourceTree = "<group>"; };
025A47502A336B05008BF85A /* DashboardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardViewController.swift; sourceTree = "<group>"; };
025A47512A336B05008BF85A /* DashboardViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardViewModel.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -221,6 +228,7 @@
02892EC52A585558001A3DB4 /* Networking */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Networking; sourceTree = "<group>"; };
02892EC92A599CBC001A3DB4 /* Container+Networking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Container+Networking.swift"; sourceTree = "<group>"; };
0296F7962A43491B00DBC86A /* FacebookAuthenticator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FacebookAuthenticator.swift; sourceTree = "<group>"; };
02CB9B632A6ADE4E00C1E765 /* DefaultLoginUseCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultLoginUseCaseTests.swift; sourceTree = "<group>"; };
02EEC3FA2A4C22C90007DA0C /* SavedRecipesViewModelMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SavedRecipesViewModelMock.swift; sourceTree = "<group>"; };
02EEC3FC2A4C23090007DA0C /* SavedRecipesViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SavedRecipesViewControllerTests.swift; sourceTree = "<group>"; };
02EEC3FE2A4C244A0007DA0C /* SavedRecipesViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SavedRecipesViewModelTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -262,6 +270,8 @@
79311FD72A19214700764707 /* UITextField+Style.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextField+Style.swift"; sourceTree = "<group>"; };
798B59B12A5D15E600E4DCFF /* MealCategories.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MealCategories.swift; sourceTree = "<group>"; };
79B65D272A0FB4310042CC46 /* UIButton+Style.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+Style.swift"; sourceTree = "<group>"; };
79FC924E2A704DC30001F255 /* RegisterUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisterUseCase.swift; sourceTree = "<group>"; };
79FC92502A705BE80001F255 /* DefaultRegisterUseCaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultRegisterUseCaseTests.swift; sourceTree = "<group>"; };
A21C51F82A42FF8D00850B15 /* SavedRecipesTableViewCellTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SavedRecipesTableViewCellTests.swift; sourceTree = "<group>"; };
A21C51FA2A43036A00850B15 /* UITableViewMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITableViewMock.swift; sourceTree = "<group>"; };
A27861142A445E8E00BA7018 /* UITableView+RegisterNib.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableView+RegisterNib.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -308,6 +318,7 @@
6D611B9F2A299E3600A1FC65 /* GoogleSignInSwift in Frameworks */,
025511B72A3C623000295B91 /* NewRelic in Frameworks */,
6DDA138D2A1109E8004390D4 /* Factory in Frameworks */,
02557D732A697E8E0022756A /* Domain in Frameworks */,
0296F7952A4342B500DBC86A /* FacebookLogin in Frameworks */,
6D611B9D2A299E3600A1FC65 /* GoogleSignIn in Frameworks */,
);
Expand Down Expand Up @@ -400,7 +411,6 @@
025511BC2A3C656300295B91 /* Recipe.swift */,
025511BA2A3C655200295B91 /* SavedRecipe.swift */,
798B59B12A5D15E600E4DCFF /* MealCategories.swift */,
0286F2852A5EEB1800F20478 /* RandomMealEntity.swift */,
C972DB2E2A5F6F91000041D1 /* FilterByMainIngredient.swift */,
6D6B89AC2A5DE99F00E52F4C /* FilterByArea.swift */,
0286F2852A5EEB1800F20478 /* RandomMealEntity.swift */,
Expand Down Expand Up @@ -441,6 +451,15 @@
path = CreateAccount;
sourceTree = "<group>";
};
02557D6F2A697D8E0022756A /* UseCases */ = {
isa = PBXGroup;
children = (
02557D702A697DF90022756A /* LoginUseCase.swift */,
79FC924E2A704DC30001F255 /* RegisterUseCase.swift */,
);
path = UseCases;
sourceTree = "<group>";
};
025A474E2A336AE3008BF85A /* Dashboard */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -507,6 +526,7 @@
027DDA122A0E6A660052818C = {
isa = PBXGroup;
children = (
02557D6E2A697C3D0022756A /* Domain */,
02892EC52A585558001A3DB4 /* Networking */,
027DDA1D2A0E6A660052818C /* Healthy */,
027DDA342A0E6A680052818C /* HealthyTests */,
Expand All @@ -530,6 +550,9 @@
isa = PBXGroup;
children = (
027DDA4F2A0E745F0052818C /* Classes */,
027DDA202A0E6A660052818C /* SceneDelegate.swift */,
027DDA1E2A0E6A660052818C /* AppDelegate.swift */,
025511C32A3D058800295B91 /* AppCoordinator.swift */,
027DDA4E2A0E74490052818C /* Resources */,
);
path = Healthy;
Expand Down Expand Up @@ -576,10 +599,8 @@
027DDA542A0E76C50052818C /* ReusableViews */,
027DDA552A0E76DC0052818C /* Services */,
025A47832A337337008BF85A /* System */,
02557D6F2A697D8E0022756A /* UseCases */,
027DDA532A0E76A00052818C /* Utilities */,
025511C32A3D058800295B91 /* AppCoordinator.swift */,
027DDA1E2A0E6A660052818C /* AppDelegate.swift */,
027DDA202A0E6A660052818C /* SceneDelegate.swift */,
);
path = Classes;
sourceTree = "<group>";
Expand Down Expand Up @@ -665,6 +686,15 @@
name = Frameworks;
sourceTree = "<group>";
};
02CB9B5F2A6AD5DD00C1E765 /* LoginUseCase */ = {
isa = PBXGroup;
children = (
02CB9B632A6ADE4E00C1E765 /* DefaultLoginUseCaseTests.swift */,
79FC92502A705BE80001F255 /* DefaultRegisterUseCaseTests.swift */,
);
path = LoginUseCase;
sourceTree = "<group>";
};
02EEC3F92A4C22B70007DA0C /* Mocks */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -818,6 +848,7 @@
6DFEC6202A2E97FF0090B2E2 /* Modules */ = {
isa = PBXGroup;
children = (
02CB9B5F2A6AD5DD00C1E765 /* LoginUseCase */,
6DA228F92A431FC60011E43E /* Search */,
B2B7AEE22A3B4CE500AF04F5 /* MainTabBarController */,
A21C51F62A42FF6400850B15 /* SavedRecipes */,
Expand Down Expand Up @@ -1075,6 +1106,7 @@
0296F7922A4342B500DBC86A /* FacebookCore */,
0296F7942A4342B500DBC86A /* FacebookLogin */,
02892EC72A58575C001A3DB4 /* Networking */,
02557D722A697E8E0022756A /* Domain */,
);
productName = Healthy;
productReference = 027DDA1B2A0E6A660052818C /* Healthy.app */;
Expand Down Expand Up @@ -1328,13 +1360,15 @@
025511BD2A3C656300295B91 /* Recipe.swift in Sources */,
0255119D2A3C5D7300295B91 /* SearchViewModelType.swift in Sources */,
6DF5250C2A1E855F0027502C /* LoginViewModelType.swift in Sources */,
79FC924F2A704DC30001F255 /* RegisterUseCase.swift in Sources */,
27C7C7F72A4341A300FECE25 /* Logging.swift in Sources */,
0229242A2A33A137009290A8 /* UIView+Helpers.swift in Sources */,
798B59B22A5D15E600E4DCFF /* MealCategories.swift in Sources */,
A27861152A445E8E00BA7018 /* UITableView+RegisterNib.swift in Sources */,
79311FD82A19214700764707 /* UITextField+Style.swift in Sources */,
0255119F2A3C5D7300295B91 /* SearchViewModel.swift in Sources */,
B2D402DF2A3BB1D700FDB941 /* UILabelStyle.swift in Sources */,
02557D712A697DF90022756A /* LoginUseCase.swift in Sources */,
A2FA41112A44412500C9C9A0 /* UIView+Style.swift in Sources */,
6D2145472A44C9EB0085C519 /* SearchFilter.swift in Sources */,
79311FD02A191D3700764707 /* FormTextField.swift in Sources */,
Expand Down Expand Up @@ -1378,6 +1412,7 @@
6DFEC6232A2E982C0090B2E2 /* LoginViewControllerTests.swift in Sources */,
B85D26A72A3902DF000A463D /* EmailValidatorsTests.swift in Sources */,
6DFEC6252A2EA5770090B2E2 /* LoginViewModelMock.swift in Sources */,
02CB9B642A6ADE4E00C1E765 /* DefaultLoginUseCaseTests.swift in Sources */,
B29ABA5C2A3469CA00171A0C /* MainTapBarControllerTest.swift in Sources */,
A21C51FB2A43036A00850B15 /* UITableViewMock.swift in Sources */,
A21C51F92A42FF8D00850B15 /* SavedRecipesTableViewCellTests.swift in Sources */,
Expand All @@ -1386,6 +1421,7 @@
02279EA72A3373C400C607AD /* CreateAccountViewModelTests.swift in Sources */,
02EEC3FB2A4C22C90007DA0C /* SavedRecipesViewModelMock.swift in Sources */,
C9E6BBE92A38D7EA0073E51A /* SplashViewControllerTest.swift in Sources */,
79FC92512A705BE80001F255 /* DefaultRegisterUseCaseTests.swift in Sources */,
206FF79A2A3A32DD00130CA4 /* CreateViewModelMock.swift in Sources */,
6DA228FB2A431FF30011E43E /* SearchViewModelTests.swift in Sources */,
6D9D97A72A4B188400BB3589 /* PublisherMultibleValueSpy.swift in Sources */,
Expand Down Expand Up @@ -1768,6 +1804,10 @@
package = 025511B52A3C623000295B91 /* XCRemoteSwiftPackageReference "newrelic-ios-agent-spm" */;
productName = NewRelic;
};
02557D722A697E8E0022756A /* Domain */ = {
isa = XCSwiftPackageProductDependency;
productName = Domain;
};
02892EC72A58575C001A3DB4 /* Networking */ = {
isa = XCSwiftPackageProductDependency;
productName = Networking;
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import UIKit
import Combine

// MARK: - CreateAccountViewController
final class CreateAccountViewController: UIViewController {

Expand All @@ -19,7 +21,8 @@ final class CreateAccountViewController: UIViewController {
// MARK: Properties

private let viewModel: CreateAccountViewModelType

private var subscriptions: Set<AnyCancellable> = []

// MARK: Init

init(viewModel: CreateAccountViewModelType) {
Expand Down Expand Up @@ -63,9 +66,9 @@ private extension CreateAccountViewController {
}

func configureViewModel() {
viewModel.configureButtonEnabled { [weak self] isEnabled in
self?.signUpButton.isEnabled = isEnabled
}
bindLoadingIndicator()
bindErrorMessage()
bindButtonState()
}
}

Expand All @@ -89,6 +92,43 @@ private extension CreateAccountViewController {
}

@objc private func didTapSignUp(_ sender: Any) {
viewModel.performSignUp()
}
}

// MARK: - Configure ViewModel

private extension CreateAccountViewController {
func bindLoadingIndicator() {
viewModel.loadingIndicatorPublisher
.sink { [weak self] isLoading in
guard let self = self else { return }
switch isLoading {
case true:
self.signUpButton.startAnimating()
case false:
self.signUpButton.stopAnimating()
}
}
.store(in: &subscriptions)
}

func bindErrorMessage() {
viewModel.errorPublisher
.sink { error in
let alertController = UIAlertController(
title: "Error!!",
message: error.localizedDescription,
preferredStyle: .alert)

self.present(alertController, animated: true)
}
.store(in: &subscriptions)
}

func bindButtonState() {
viewModel.registerButtonEnabledPublisher
.assign(to: \.isEnabled, on: signUpButton)
.store(in: &subscriptions)
}
}
Loading