Skip to content

Commit

Permalink
[DEV][Developed Detail]
Browse files Browse the repository at this point in the history
  • Loading branch information
developersancho committed Mar 2, 2022
1 parent 41f8829 commit c88efe0
Show file tree
Hide file tree
Showing 12 changed files with 246 additions and 17 deletions.
16 changes: 16 additions & 0 deletions SwiftRorty.iOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
E2555C1127A872F2007E5266 /* HomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2555C1027A872F2007E5266 /* HomeScreen.swift */; };
E2555C1327A872FF007E5266 /* SplashScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2555C1227A872FF007E5266 /* SplashScreen.swift */; };
E267D17727C9189700254746 /* LottieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E267D17627C9189700254746 /* LottieView.swift */; };
E26BD39F27CFFE51006CA548 /* DetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E26BD39E27CFFE51006CA548 /* DetailViewModel.swift */; };
E26BD3A127D002B0006CA548 /* GetCharacterDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = E26BD3A027D002B0006CA548 /* GetCharacterDetail.swift */; };
E26BD3A327D01629006CA548 /* DetailHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E26BD3A227D01629006CA548 /* DetailHeaderView.swift */; };
E26BD3A527D01769006CA548 /* DetailContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E26BD3A427D01769006CA548 /* DetailContentView.swift */; };
E28A38BF27C94730005DD497 /* DtoExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E28A38BE27C94730005DD497 /* DtoExtension.swift */; };
E2991AA927AC72ED00BF4B9A /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2991AA827AC72ED00BF4B9A /* Status.swift */; };
E2991AAF27AC740800BF4B9A /* LocationInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2991AAE27AC740800BF4B9A /* LocationInfo.swift */; };
Expand Down Expand Up @@ -135,6 +139,10 @@
E2555C1027A872F2007E5266 /* HomeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreen.swift; sourceTree = "<group>"; };
E2555C1227A872FF007E5266 /* SplashScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreen.swift; sourceTree = "<group>"; };
E267D17627C9189700254746 /* LottieView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LottieView.swift; sourceTree = "<group>"; };
E26BD39E27CFFE51006CA548 /* DetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailViewModel.swift; sourceTree = "<group>"; };
E26BD3A027D002B0006CA548 /* GetCharacterDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetCharacterDetail.swift; sourceTree = "<group>"; };
E26BD3A227D01629006CA548 /* DetailHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailHeaderView.swift; sourceTree = "<group>"; };
E26BD3A427D01769006CA548 /* DetailContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailContentView.swift; sourceTree = "<group>"; };
E28A38BE27C94730005DD497 /* DtoExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DtoExtension.swift; sourceTree = "<group>"; };
E2991AA827AC72ED00BF4B9A /* Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = "<group>"; };
E2991AAE27AC740800BF4B9A /* LocationInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationInfo.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -281,6 +289,7 @@
isa = PBXGroup;
children = (
E2555C0627A87252007E5266 /* GetCharacters.swift */,
E26BD3A027D002B0006CA548 /* GetCharacterDetail.swift */,
);
path = domain;
sourceTree = "<group>";
Expand Down Expand Up @@ -379,7 +388,10 @@
E2291D6827A5EA72006D3FD8 /* detail */ = {
isa = PBXGroup;
children = (
E26BD3A227D01629006CA548 /* DetailHeaderView.swift */,
E2555C0E27A872E4007E5266 /* DetailScreen.swift */,
E26BD39E27CFFE51006CA548 /* DetailViewModel.swift */,
E26BD3A427D01769006CA548 /* DetailContentView.swift */,
);
path = detail;
sourceTree = "<group>";
Expand Down Expand Up @@ -817,6 +829,7 @@
E2D5A98327C96E3E0017DA32 /* APIMethod.swift in Sources */,
E232FA1B27CD6DC10073FCC8 /* FontTemplateModifier.swift in Sources */,
E2D5A99127C9986C0017DA32 /* CharacterRow.swift in Sources */,
E26BD39F27CFFE51006CA548 /* DetailViewModel.swift in Sources */,
E232FA1727CD6C9D0073FCC8 /* AppFont.swift in Sources */,
E2991AAF27AC740800BF4B9A /* LocationInfo.swift in Sources */,
E2291D6E27A5F362006D3FD8 /* CharactersViewModel.swift in Sources */,
Expand All @@ -833,18 +846,21 @@
E2D5A98927C977A30017DA32 /* BaseError.swift in Sources */,
E2D5A98B27C977EF0017DA32 /* Decoder.swift in Sources */,
E2D5A98D27C97AC20017DA32 /* APIEndpoint.swift in Sources */,
E26BD3A527D01769006CA548 /* DetailContentView.swift in Sources */,
E2555C0727A87252007E5266 /* GetCharacters.swift in Sources */,
E2AD77A127CAD8E1006565C2 /* AppModule.swift in Sources */,
E2991AB927AC76FA00BF4B9A /* Location.swift in Sources */,
E2555BFF27A87181007E5266 /* PageInfo.swift in Sources */,
E2991ABD27AC777300BF4B9A /* CharacterResponse.swift in Sources */,
E2512DAC27C82A5E00FC6129 /* LocationDto.swift in Sources */,
E26BD3A327D01629006CA548 /* DetailHeaderView.swift in Sources */,
E2AD779C27CAC242006565C2 /* RestClientErrors.swift in Sources */,
E2555C0327A87220007E5266 /* FavoriteDao.swift in Sources */,
E2555C0F27A872E4007E5266 /* DetailScreen.swift in Sources */,
E2D5A98727C9771D0017DA32 /* APIClientImpl.swift in Sources */,
E2991AA927AC72ED00BF4B9A /* Status.swift in Sources */,
E2555C0127A87209007E5266 /* CharacterService.swift in Sources */,
E26BD3A127D002B0006CA548 /* GetCharacterDetail.swift in Sources */,
E2555C0927A87292007E5266 /* FavoritesScreen.swift in Sources */,
E2291D6C27A5F33F006D3FD8 /* CharactersScreen.swift in Sources */,
E2D5A98F27C97CEC0017DA32 /* URLRequest.swift in Sources */,
Expand Down
3 changes: 2 additions & 1 deletion SwiftRorty.iOS/data/model/dto/KeyValueModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@

import Foundation

struct KeyValueModel {
struct KeyValueModel: Identifiable {
let id: Int?
let key: String?
let value: String?
}
6 changes: 5 additions & 1 deletion SwiftRorty.iOS/data/remote/CharacterService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ import Resolver

protocol CharacterService {
func getCharacters(page: Int) -> AnyPublisher<CharacterResponse, Error>
func getCharacter(characterId: Int) -> AnyPublisher<CharacterInfo, Error>
}

class CharacterServiceImpl: CharacterService {

@Injected private var restClient: RestClient

func getCharacters(page: Int) -> AnyPublisher<CharacterResponse, Error> {
restClient.get(APIEndpoint.characters(page))
}

func getCharacter(characterId: Int) -> AnyPublisher<CharacterInfo, Error> {
restClient.get(APIEndpoint.character(characterId))
}
}
4 changes: 4 additions & 0 deletions SwiftRorty.iOS/data/repository/CharacterRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@ class CharacterRepository {
func getCharacters(page: Int) -> AnyPublisher<CharacterResponse, Error> {
remoteService.getCharacters(page: page)
}

func getCharacter(characterId: Int) -> AnyPublisher<CharacterInfo, Error> {
remoteService.getCharacter(characterId: characterId)
}
}
1 change: 1 addition & 0 deletions SwiftRorty.iOS/di/AppModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ extension Resolver: ResolverRegistering {

private static func registerDomain() {
register { GetCharacters() }
register { GetCharacterDetail() }
}

}
20 changes: 20 additions & 0 deletions SwiftRorty.iOS/domain/GetCharacterDetail.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// GetCharacterDetail.swift
// SwiftRorty.iOS
//
// Created by developersancho on 2.03.2022.
//

import Foundation
import Combine
import Resolver

class GetCharacterDetail {
@Injected private var repository: CharacterRepository

func invoke(characterId: Int) -> AnyPublisher<CharacterDto, Error> {
repository.getCharacter(characterId: characterId).map { (response: CharacterInfo) in
response.toCharacterDto()
}.eraseToAnyPublisher()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// DetailContentView.swift
// SwiftRorty.iOS
//
// Created by developersancho on 3.03.2022.
//

import SwiftUI

struct DetailContentView: View {
var contents: [KeyValueModel] = []

var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 8, style: .continuous)
.fill(Color.Card).shadow(radius: 1)

VStack(alignment: .leading, spacing: 12) {
ForEach(contents, id: \.id) { content in
HStack(alignment: .center) {
Text(content.key!)
.fontTemplate(AppFontTemplate.body4)
.redacted(reason: content.key == nil ? .placeholder : [])
Spacer()
Text(content.value!)
.fontTemplate(AppFontTemplate.body2)
.redacted(reason: content.value == nil ? .placeholder : [])
}
Divider()
}
}.padding(EdgeInsets(top: 16, leading: 12, bottom: 0, trailing: 12))
}
}
}

struct DetailContentView_Previews: PreviewProvider {
static var previews: some View {
DetailContentView()
}
}
39 changes: 39 additions & 0 deletions SwiftRorty.iOS/presentation/features/detail/DetailHeaderView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// DetailHeaderView.swift
// SwiftRorty.iOS
//
// Created by developersancho on 3.03.2022.
//

import Foundation
import SwiftUI

struct DetailHeaderView: View {
var dto: CharacterDto?

var body: some View {
if let image = dto?.image,
let url = URL(string: image) {
AsyncImage(url: url) { image in
image.resizable()
} placeholder: {
Color.gray
}
.aspectRatio(contentMode: .fit)
.frame(width: 200, height: 200)
.clipShape(RoundedRectangle(cornerRadius: 16))
.padding(EdgeInsets(top: 16, leading: 0, bottom: 16, trailing: 0))
} else {
RoundedRectangle(cornerRadius: 16)
.padding(EdgeInsets(top: 16, leading: 0, bottom: 16, trailing: 0))
.frame(width: 200, height: 200)
.foregroundColor(.gray)
}
}
}

struct DetailHeaderView_Previews: PreviewProvider {
static var previews: some View {
DetailHeaderView()
}
}
27 changes: 25 additions & 2 deletions SwiftRorty.iOS/presentation/features/detail/DetailScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,37 @@
import SwiftUI

struct DetailScreen: View {
@State var characterId: Int = 0
@StateObject
private var viewModel = DetailViewModel()
@State
private var characterId: Int = 0

init(id: Int) {
_characterId = State(initialValue: id)
UITabBar.appearance().barTintColor = UIColor(Color.Primary)
}

var body: some View {
Text("Detail Screen Character Id is => \(characterId)")
ZStack {
Color.Background.edgesIgnoringSafeArea(.all)
ScrollView {
LazyVStack {
DetailHeaderView(dto: viewModel.dto)
DetailContentView(contents: viewModel.details)
}.padding(12)
}
}
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
VStack {
Text("Details").fontTemplate(AppFontTemplate.title)
}
}
}
.onAppear(perform: {
viewModel.loadDetail(characterId: characterId)
})
}
}

Expand Down
73 changes: 73 additions & 0 deletions SwiftRorty.iOS/presentation/features/detail/DetailViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// DetailViewModel.swift
// SwiftRorty.iOS
//
// Created by developersancho on 2.03.2022.
//

import Foundation
import UIKit
import Combine
import Resolver

class DetailViewModel: ObservableObject {
@Injected
private var getCharacterDetail: GetCharacterDetail
@Published
var dto: CharacterDto?
@Published
var details: [KeyValueModel] = []
private var cancelables = [AnyCancellable]()


func loadDetail(characterId: Int) {
getCharacterDetail.invoke(characterId: characterId)
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { _ in }, receiveValue: { [weak self] response in
self?.dto = response
self?.details = self!.getDetails(character: response)
})
.store(in: &cancelables)
}

func getDetails(character: CharacterDto) -> [KeyValueModel] {
var list: [KeyValueModel] = []
list.append(
KeyValueModel(
id: 0,
key: "Name",
value: character.name
)
)
list.append(
KeyValueModel(
id: 1,
key: "Species",
value: character.species
)
)
list.append(
KeyValueModel(
id: 2,
key: "Gender",
value: character.gender
)
)
list.append(
KeyValueModel(
id: 3,
key: "Last Know Location",
value: character.origin?.name ?? "-"
)
)
list.append(
KeyValueModel(
id: 4,
key: "Location",
value: character.location?.name ?? "-"
)
)

return list
}
}
30 changes: 17 additions & 13 deletions SwiftRorty.iOS/presentation/features/home/HomeScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ import SwiftUI

struct HomeScreen: View {

// init () {
// let coloredAppearance = UINavigationBarAppearance()
//
// // this overrides everything you have set up earlier.
// coloredAppearance.configureWithTransparentBackground()
// coloredAppearance.backgroundColor = UIColor(Color.Primary)
//
// // to make everything work normally
// UINavigationBar.appearance().standardAppearance = coloredAppearance
// UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
// }
// init () {
// let coloredAppearance = UINavigationBarAppearance()
//
// // this overrides everything you have set up earlier.
// coloredAppearance.configureWithTransparentBackground()
// coloredAppearance.backgroundColor = UIColor(Color.Primary)
//
// // to make everything work normally
// UINavigationBar.appearance().standardAppearance = coloredAppearance
// UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
// }

@State var uiTabarController: UITabBarController?

var body: some View {
TabView {
Expand All @@ -32,10 +34,12 @@ struct HomeScreen: View {
SettingsScreen().tabItem {
Label("Settings", systemImage: "gearshape")
}
}.onAppear() {
}
.onAppear() {
UITabBar.appearance().barTintColor = UIColor(Color.Primary)
UITabBar.appearance().unselectedItemTintColor = UIColor(Color.UnSelectedBottomItem)
}.accentColor(Color.SelectedBottomItem)
}
.accentColor(Color.SelectedBottomItem)
}
}

Expand Down
4 changes: 4 additions & 0 deletions SwiftRorty.iOS/theme/fonts/AppFontTemplate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,8 @@ struct AppFontTemplate {
weight: .bold,
foregroundColor: .Text)

static let body4 = FontTemplate(font: Font.custom(AppFont.bold.rawValue, size: 14.0),
weight: .bold,
foregroundColor: .Text)

}

0 comments on commit c88efe0

Please sign in to comment.