Skip to content
Merged
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
24 changes: 24 additions & 0 deletions FakeNFT.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
5019A4CE2DE1E899009A5AF8 /* FakeNftApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5019A4CD2DE1E899009A5AF8 /* FakeNftApp.swift */; };
5019A4D02DE1E8E0009A5AF8 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5019A4CF2DE1E8E0009A5AF8 /* ContentView.swift */; };
558E39E72C68CE0A00FB86AC /* NftService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 558E39E62C68CE0900FB86AC /* NftService.swift */; };
793BCC8E2DEEF05000DF1252 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 793BCC8D2DEEF05000DF1252 /* WebView.swift */; };
793BCC902DEEF06800DF1252 /* WebViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 793BCC8F2DEEF06800DF1252 /* WebViewRepresentable.swift */; };
793BCC922DEEF46600DF1252 /* Statistics.md in Resources */ = {isa = PBXBuildFile; fileRef = 793BCC912DEEF46600DF1252 /* Statistics.md */; };
793BCC942DEEF47200DF1252 /* CartAnisimov.md in Resources */ = {isa = PBXBuildFile; fileRef = 793BCC932DEEF47200DF1252 /* CartAnisimov.md */; };
79D0C7532DE396AC00D53241 /* Tab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79D0C7522DE396AC00D53241 /* Tab.swift */; };
79D0C7562DE3973200D53241 /* TabBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79D0C7552DE3973200D53241 /* TabBarView.swift */; };
79D0C7592DE39C3800D53241 /* NavigationBarStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 79D0C7582DE39C3800D53241 /* NavigationBarStyle.swift */; };
Expand Down Expand Up @@ -78,6 +82,10 @@
5019A4CD2DE1E899009A5AF8 /* FakeNftApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakeNftApp.swift; sourceTree = "<group>"; };
5019A4CF2DE1E8E0009A5AF8 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
558E39E62C68CE0900FB86AC /* NftService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NftService.swift; sourceTree = "<group>"; };
793BCC8D2DEEF05000DF1252 /* WebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = "<group>"; };
793BCC8F2DEEF06800DF1252 /* WebViewRepresentable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewRepresentable.swift; sourceTree = "<group>"; };
793BCC912DEEF46600DF1252 /* Statistics.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Statistics.md; sourceTree = "<group>"; };
793BCC932DEEF47200DF1252 /* CartAnisimov.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CartAnisimov.md; sourceTree = "<group>"; };
79D0C7522DE396AC00D53241 /* Tab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tab.swift; sourceTree = "<group>"; };
79D0C7552DE3973200D53241 /* TabBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarView.swift; sourceTree = "<group>"; };
79D0C7582DE39C3800D53241 /* NavigationBarStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarStyle.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -115,6 +123,7 @@
0CF2C2D92A783C1600FDC837 /* Common */ = {
isa = PBXGroup;
children = (
793BCC8C2DEEF03300DF1252 /* WebView */,
79D0C75B2DE39F3900D53241 /* LoadingView */,
0CF2C2DE2A784C4C00FDC837 /* Protocols */,
);
Expand Down Expand Up @@ -269,9 +278,20 @@
path = Requests;
sourceTree = "<group>";
};
793BCC8C2DEEF03300DF1252 /* WebView */ = {
isa = PBXGroup;
children = (
793BCC8D2DEEF05000DF1252 /* WebView.swift */,
793BCC8F2DEEF06800DF1252 /* WebViewRepresentable.swift */,
);
path = WebView;
sourceTree = "<group>";
};
79D0C74F2DE393F600D53241 /* Docs */ = {
isa = PBXGroup;
children = (
793BCC912DEEF46600DF1252 /* Statistics.md */,
793BCC932DEEF47200DF1252 /* CartAnisimov.md */,
);
path = Docs;
sourceTree = "<group>";
Expand Down Expand Up @@ -446,6 +466,8 @@
files = (
E1CD40DC2A96BECC00BE7FE8 /* Localizable.strings in Resources */,
3F6806A029CBBAF200B4F915 /* Assets.xcassets in Resources */,
793BCC942DEEF47200DF1252 /* CartAnisimov.md in Resources */,
793BCC922DEEF46600DF1252 /* Statistics.md in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -482,6 +504,7 @@
3F6806D529CBBEC700B4F915 /* NetworkTask.swift in Sources */,
558E39E72C68CE0A00FB86AC /* NftService.swift in Sources */,
0C79EE6C2A76DE2E00EE90EA /* ServicesAssemly.swift in Sources */,
793BCC902DEEF06800DF1252 /* WebViewRepresentable.swift in Sources */,
79D0C7532DE396AC00D53241 /* Tab.swift in Sources */,
0CFCB74E2A7817DC0009A829 /* NftStorage.swift in Sources */,
3FC8C39129D2453B0081F015 /* ExamplePutRequest.swift in Sources */,
Expand All @@ -491,6 +514,7 @@
3F6806D129CBBE6B00B4F915 /* NetworkClient.swift in Sources */,
79D0C7562DE3973200D53241 /* TabBarView.swift in Sources */,
0C79EE632A76DD1900EE90EA /* RequestConstants.swift in Sources */,
793BCC8E2DEEF05000DF1252 /* WebView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
44 changes: 44 additions & 0 deletions FakeNFT/Docs/CartAnisimov.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Анисимов Максим Сергеевич
Когорта: 22
Группа: 2
Эпик: Корзина

Ссылка на доску: [ссылка](https://github.com/users/Maxoscaro/projects/1/views/4)
Comment on lines +1 to +6
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Спасибо, что мой тоже закинула)



# Декомпозиция эпика Корзина

## Модуль 1:

#### Верстка
- Основной экран корзины и состояние пустой корзины (est: 1 час; fact: x часов).
- Ячейка с картинкой и ценой (est: 1 час; fact: x часов).
- Верстка кнопки покупки с ценой - (est: 1 час; fact: х часов)

#### Логика
- Сортировка NFT (по названию, рейтингу, цене) (est: 1 час; fact: x часов).
- Сохранение выбранного способа сортировки (est: 1 час; fact: x часов).
- Заполнение ячеек данными из сервиса NFTService - (est: 2 часа; fact: х часов)
- Навигация на экран выбора способа оплаты (est: 40 минут; fact: x часов).

## Модуль 2:

#### Верстка
- Экран выбора способа оплаты (est: 1 час; fact: x часов).
- Ячейка с картинкой и криптовалютами (est: 50 минут; fact: x часов).
- Кнопка оплатить (est: 30 минут; fact: x часов).
- Ссылка на пользовательское соглашение (est: 30 минут; fact: x часов).

#### Логика
- Открытие сайта пользователя в WebView (est: 30 минут; fact: x часов).
- Навигация на экран успешной покупки (est: 20 минут; fact: x часов).

## Module 3:

#### Верстка
- Экран удаления товара из корзины (est: 50 минут; fact: x часов).
- Экран успешной покупки (est: 1 час; fact: x часов).

#### Логика
- Логика покупки: удаление из корзины и добавление в аккаунт пользователя (est: 2 часа; fact: x часов).
- Обработка возврата в каталог (est: 1 час; fact: x часов).
55 changes: 55 additions & 0 deletions FakeNFT/Docs/Statistics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Кирпинева Анастасия Валерьевна

Когорта: 22

Группа: 2

Эпик: Статистика

Ссылка на доску: [ссылка](https://github.com/users/Maxoscaro/projects/1/views/3)


# Декомпозиция эпика Статистика

## Модуль 1:

#### Верстка
- Экран рейтинга (кнопка сортировки, список пользователей) (est: 30 минут; fact: x часов).
- Ячейка для списка пользователей на экране рейтинга (est: 1 час; fact: x часов).

#### Логика
- Сортировка списка пользователей (по имени, рейтингу) (est: 1 час; fact: x часов).
- Сохранение выбранного способа сортировки (est: 1 час; fact: x часов).
- Навигация на экран информации о пользователе (est: 20 минут; fact: x часов).

#### Работа с сетью
- Создать запрос на получение списка пользователей (est: 2 часа; fact: x часов).
- Подключить запрос (est: 1 час; fact: x часов).

## Модуль 2:

#### Верстка
- Экран информации о пользователе (аватар, имя, описание) (est: 30 минут; fact: x часов).
- Кнопка перехода на сайт пользователя (est: 30 минут; fact: x часов).
- Кнопка перехода на экран коллекции пользователя (est: 30 минут; fact: x часов).
- Создать WebView (est: 1 час; fact: x часов).

#### Логика
- Открытие сайта пользователя в WebView (est: 30 минут; fact: x часов).
- Навигация на экран коллекции пользователя (est: 20 минут; fact: x часов).

## Module 3:

#### Верстка
- Экран коллекции пользователя (est: 20 минут; fact: x часов).
- Ячейка с информацией об NFT (est: 1 час; fact: x часов).

#### Логика
- Обработка нажатия на сердечко (est: 1 час; fact: x часов).
- Обработка нажатия на кнопку корзины (добавить/удалить NFT) (est: 1 час; fact: x часов).

#### Работа с сетью
- Загрузка и отображение изображений NFT (est: 1 час; fact: x часов).
- Запрос на добавление/удаление лайка (est: 1 час; fact: x часов).
- Запрос на добавление NFT в корзину (est: 1 час; fact: x часов).
- Запрос на удаление NFT из корзины (est: 1 час; fact: x часов).
4 changes: 4 additions & 0 deletions FakeNFT/FakeNftApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ import SwiftUI

@main
struct FakeNftApp: App {

@StateObject var service = ServicesAssembly()

var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(service)
}
}
}
Expand Down
34 changes: 34 additions & 0 deletions FakeNFT/Scenes /Common/WebView/WebView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// WebView.swift
// FakeNFT
//
// Created by Anastasia on 03.06.2025.
//

import SwiftUI

struct WebView: View {
@State private var isLoading = true
let url: URL?

var body: some View {
ZStack {
WebViewRepresentable(isLoading: $isLoading, url: url)
LoadingView()
.opacity(isLoading ? 1 : 0)
}
.edgesIgnoringSafeArea(.all)
.modifier(NavigationBarStyle(
title: nil,
backButtonHidden: false,
filterButtonHidden: true,
filterButtonTapHandler: { }
))
}
}

#Preview {
NavigationView {
WebView(url: URL(string: "https://practicum.yandex.ru"))
}
}
44 changes: 44 additions & 0 deletions FakeNFT/Scenes /Common/WebView/WebViewRepresentable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// WebViewRepresentable.swift
// FakeNFT
//
// Created by Anastasia on 03.06.2025.
//

import SwiftUI
import WebKit

struct WebViewRepresentable: UIViewRepresentable {
@Binding var isLoading: Bool
let url: URL?

func makeUIView(context: Context) -> WKWebView {
WKWebView()
}

func updateUIView(_ webView: WKWebView, context: Context) {
webView.navigationDelegate = context.coordinator
webView.isOpaque = false
webView.backgroundColor = .white

if let url = url {
webView.load(URLRequest(url: url))
}
}

func makeCoordinator() -> Coordinator {
Coordinator(parent: self)
}

final class Coordinator: NSObject, WKNavigationDelegate {
var parent: WebViewRepresentable

init(parent: WebViewRepresentable) {
self.parent = parent
}

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
parent.isLoading = false
}
}
}
Comment on lines +33 to +44
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

не думаю, что это критично, но я бы вынес класс в отдельный файл, просто для чистоты

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coordinator, это вспомогательный объект, который связан только с WebViewRepresentable, и он больше нигде не используется.

3 changes: 2 additions & 1 deletion FakeNFT/Scenes /ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import SwiftUI

struct ContentView: View {

@EnvironmentObject var service: ServicesAssembly
@State private var isTabBarHidden = false
@State private var selectedTab = Tab.profile
@StateObject private var cartViewModel = CartViewViewModel()

var body: some View {
ZStack(alignment: .bottom) {
Expand All @@ -37,4 +37,5 @@ struct ContentView: View {

#Preview {
ContentView()
.environmentObject(ServicesAssembly())
}
8 changes: 5 additions & 3 deletions FakeNFT/Services/ServicesAssemly.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
final class ServicesAssembly {
import Foundation

final class ServicesAssembly: ObservableObject {

private let networkClient: NetworkClient
private let nftStorage: NftStorage

init(
networkClient: NetworkClient,
nftStorage: NftStorage
networkClient: NetworkClient = DefaultNetworkClient(),
nftStorage: NftStorage = NftStorageImpl()
) {
self.networkClient = networkClient
self.nftStorage = nftStorage
Expand Down