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
2 changes: 2 additions & 0 deletions Bored/Models/ActivityDetail.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import Foundation

// Me parece que esse struct não precisa existir. Podemos deletar ele.
// Essa função (returnImage) poderia ser colocada no seu ActivityDetailsViewModel e ser chamada pela sua AcitivyDetailsView

struct ActivityDetail: Codable {
func returnImage(activityTipe: String) -> String {
Expand Down
3 changes: 3 additions & 0 deletions Bored/Models/BoredAPI.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import Foundation

// Este struct seria os dados de retorno da API? Acho que poderiamos dar um nome melhor para ele
// Sugestões: ActivityItem, ActivityDetails, ActivityResponse

struct BoredAPI: Hashable, Codable {
let activity: String
let type: String
Expand Down
3 changes: 2 additions & 1 deletion Bored/Models/CardInfo.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import Foundation

// Renomear para ActivityCategory ou ActivityType
struct CardInfo: Identifiable, Hashable {
var id = UUID()
var id = UUID() // Por uma questão de performance do SwiftUI, se houver um ID melhor, seria bom atribuir ele aqui, uma atividade possui um ID?

let label: String
let image: String
Expand Down
5 changes: 5 additions & 0 deletions Bored/Models/Colors.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import Foundation
import SwiftUI

// Colors poderia ser um enum ao invés de struct
// suas propriedades poderiam ser static let, por exemplo, static let cardBorder = ...
// dessa forma, facilita a forma que você acessa esses valores constantes
//
// Uso: Colors.cardBorder
struct Colors {
let cardBorder = Color(red: 157/255, green: 222/255, blue: 211/255)
let cardBackground = Color(red: 254/255, green: 254/255, blue: 254/255)
Expand Down
4 changes: 3 additions & 1 deletion Bored/Views/ActivityDetails/ActivityDetails.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import SwiftUI

// Quando a View representa uma tela, ou seja, não um componente, geralmente, colocamos o nome View no final.
// ActivityDetailsView
struct ActivityDetails: View {
@StateObject private var viewModel = ViewModel()
let activityType: String
let colors = Colors()
let colors = Colors() // Tornando Colors um enum com propriedades estáticas não precisaríamos dessa propriedade aqui

var body: some View {
VStack(alignment: .center, spacing: 40) {
Expand Down
24 changes: 18 additions & 6 deletions Bored/Views/CardStack/Card.swift
Original file line number Diff line number Diff line change
@@ -1,29 +1,41 @@
import SwiftUI

struct Card: View {
let colors = Colors()
let colors = Colors() // Tornando Colors um enum com propriedades estáticas não precisaríamos dessa propriedade aqui
let label: String
let image: String
// se o número de propriedades for crescer muito, vale a pena ter um struct para segurar os dados, por exemplo, CardViewModel, CardProperties, CardSettings

var body: some View {
VStack(alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/, spacing: 4) {
VStack(alignment: .center, spacing: 4) { // VStack(alignment: .center, spacing: Style.verticalSpacing)
Image(image)
.resizable()
.frame(width: 142, height: 106)
Text(label)
.font(.title2)
.fontWeight(.semibold)
.foregroundStyle(colors.titleColor)
.foregroundStyle(colors.titleColor) // .foregroundStyle(Colors.titleColor)
}
.padding(EdgeInsets(top: 16, leading: 9, bottom: 40, trailing: 9))
.background(colors.cardBackground)
.background(colors.cardBackground) // .stroke(Colors.cardBackground, lineWidth: 2)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(colors.cardBorder, lineWidth: 2)
.stroke(colors.cardBorder, lineWidth: 2) // .stroke(Colors.cardBorder, lineWidth: 2)
)
}
}

// DICA:
// Eu gosto de criar uma extension da View para colocar as constanstes, assim, evitando os números mágicos.
// Coloquei um exemplo para o espaço vertical da VStack mas serve para os outros números que estão soltos no body.

extension Card {

enum Style {
static let verticalSpacing: CGFloat = 4.0
}
}

#Preview {
Card(label: "Random", image: "random")
}
}
10 changes: 10 additions & 0 deletions Bored/Views/CardStack/CardsStack.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import SwiftUI

// Essa View é a que exibe a lista de cards? Se sim, podemos chamar de ActivityListView.swift ou ActivityCategoriesView.swift
// No fim das contas, estamos exibindo uma lista de atividades, certo?
struct CardsStack: View {

// let activityRepository: ActitivyRepository

// Esses itens poderiam ficar em uma classe separada.
let items:[CardInfo] = [
CardInfo(label: "Random", image: "random", activityType: "random"),
CardInfo(label: "Education", image: "education", activityType: "education"),
Expand All @@ -14,6 +20,10 @@ struct CardsStack: View {
CardInfo(label: "Music", image: "music", activityType: "music")
]

// var items:[CardInfo] {
// activityRepository.fetchActivities()
// }

var body: some View {
NavigationView{
ScrollView {
Expand Down
79 changes: 55 additions & 24 deletions Bored/ViewsModels/ViewModel.swift
Original file line number Diff line number Diff line change
@@ -1,29 +1,60 @@
import Foundation

// Esse ViewModel é de qual View? É sempre bom a gente deixar isso explícito.
// Um bom nome seria ActivyDetailsViewModel
class ViewModel: ObservableObject {
@Published var boredAPI: BoredAPI?

func fetch(type: String){
boredAPI = nil
guard let url = URL(string:"https://www.boredapi.com/api/activity?type=\(type)") else {return}

let task = URLSession.shared.dataTask(with: url) {
[weak self] data, _,error in
guard let data = data, error == nil else {
print(error)
return
}

do {
let boredAPI = try JSONDecoder().decode(BoredAPI.self, from: data)
DispatchQueue.main.async {
self?.boredAPI = boredAPI
}
}
catch {
print(error)
}
}
task.resume()
@Published var boredAPI: BoredAPI? // poderiamos renomear para activiyDetails
let repository: ActivyRepository

// É sempre bom ter em seus projetos uma classe que faz requests, geralmente, chamamos de Network, Networking, NetworkProvider ou NetworkManager.
// Também é bom ter uma classe responsável ou fazer as requests das acivities em específico, chamamos de ActivityRepository ou ActivityWoker
func fetch(type: String) {
activityDetails = repository.fetch(type: type)
// boredAPI = nil
// guard let url = URL(string:"https://www.boredapi.com/api/activity?type=\(type)") else { return }

// let task = URLSession.shared.dataTask(with: url) {
// [weak self] data, _,error in
// guard let data = data, error == nil else {
// print(error)
// return
// }

// do {
// let boredAPI = try JSONDecoder().decode(BoredAPI.self, from: data)
// DispatchQueue.main.async {
// self?.boredAPI = boredAPI
// }
// }
// catch {
// print(error)
// }
// }
// task.resume()
}
}

// Em outro arquivo, exemplo de Worker e/ou Repository (Acitivity)

class ActivyRepository {

let networkProvider: NetworkProvider

func fetchActivities() -> [Activity] {
[CardInfo(label: "Random", image: "random", activityType: "random"),
CardInfo(label: "Education", image: "education", activityType: "education"),
CardInfo(label: "Recreational", image: "recreational", activityType: "recreational"),
CardInfo(label: "Social", image: "social", activityType: "social"),
CardInfo(label: "Cooking", image:"cooking", activityType: "cooking"),
CardInfo(label: "Charity", image: "charity", activityType: "charity"),
CardInfo(label: "Do it yourself", image: "doYourself", activityType: "diy"),
CardInfo(label: "Relaxation", image: "relaxation", activityType: "relaxation"),
CardInfo(label: "Busy work", image: "busyWork", activityType: "busywork"),
CardInfo(label: "Music", image: "music", activityType: "music")
]
}

func fetchAcivity(type: String) -> ActivityItem {
networkProvider.fetch(url: "https://www.boredapi.com/api/activity?type=\(type)")
}
}