Skip to content

Commit

Permalink
Meal
Browse files Browse the repository at this point in the history
  • Loading branch information
hhhello0507 committed Oct 11, 2024
1 parent fa8a630 commit e44da76
Show file tree
Hide file tree
Showing 13 changed files with 391 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ class MealController(
private val mealService: MealService
) {
@GetMapping
fun getMeals(@Valid @RequestBody req: GetMealsReq = GetMealsReq.current()) =
fun getMeals(@Valid @ModelAttribute req: GetMealsReq = GetMealsReq.current()) =
mealService.getMeals(req)
}
9 changes: 5 additions & 4 deletions Graduating-iOS/Data/Network/MealService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ import Moya
import Shared

public enum MealEndpoint: MyTarget {
case fetchMeals
case fetchMeals(_ req: GetMealReq)
}

extension MealEndpoint {
public var host: String { "meals" }
public var route: Route {
switch self {
case .fetchMeals:
case .fetchMeals(let req):
.get()
.task(req.toURLParameters())
}
}

Expand All @@ -28,7 +29,7 @@ extension MealEndpoint {
public struct MealService {
public static let shared = Self()

public func fetchMeals() -> AnyPublisher<[Meal], APIError> {
runner.deepDive(MealEndpoint.fetchMeals, res: [Meal].self)
public func fetchMeals(_ req: GetMealReq) -> AnyPublisher<[Meal], APIError> {
runner.deepDive(MealEndpoint.fetchMeals(req), res: [Meal].self)
}
}
26 changes: 14 additions & 12 deletions Graduating-iOS/Graduating-Widget/Meal/MealProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,20 @@ class MealProvider: TimelineProvider {
let nextUpdate = Calendar.current.date(byAdding: .hour, value: 1, to: .now)!
let currentDate = Date()

MealService.shared.fetchMeals()
.ignoreError()
.sink { meal in
let type = MealType.from(.now)
let entry = MealEntry(
date: currentDate,
meal: meal.filter { $0.mealType == type }.first
)
let timeline = Timeline(entries: [entry], policy: .after(nextUpdate))
completion(timeline)
}
.store(in: &subscription)
MealService.shared.fetchMeals(
.init()
)
.ignoreError()
.sink { meal in
let type = MealType.from(.now)
let entry = MealEntry(
date: currentDate,
meal: meal.filter { $0.mealType == type }.first
)
let timeline = Timeline(entries: [entry], policy: .after(nextUpdate))
completion(timeline)
}
.store(in: &subscription)

}
}
17 changes: 17 additions & 0 deletions Graduating-iOS/Graduating.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
253DC2B42C7EBEAC0047C401 /* MyMoya in Frameworks */ = {isa = PBXBuildFile; productRef = 253DC2B32C7EBEAC0047C401 /* MyMoya */; };
253DC2B62C7EBEAC0047C401 /* MyShared in Frameworks */ = {isa = PBXBuildFile; productRef = 253DC2B52C7EBEAC0047C401 /* MyShared */; };
253DC2B82C7EBEB30047C401 /* MyDesignSystem in Frameworks */ = {isa = PBXBuildFile; productRef = 253DC2B72C7EBEB30047C401 /* MyDesignSystem */; };
2569F4DB2CB8B1D3006B5D7F /* SwiftUIIntrospect in Frameworks */ = {isa = PBXBuildFile; productRef = 2569F4DA2CB8B1D3006B5D7F /* SwiftUIIntrospect */; };
258172AC2C7A10CF00D2691E /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 258172AB2C7A10CF00D2691E /* WidgetKit.framework */; };
258172AE2C7A10CF00D2691E /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 258172AD2C7A10CF00D2691E /* SwiftUI.framework */; };
258172B92C7A10D100D2691E /* Graduating-WidgetExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 258172A92C7A10CF00D2691E /* Graduating-WidgetExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
Expand Down Expand Up @@ -177,6 +178,7 @@
250258802CB3CF4700ADCF68 /* GoogleMobileAds in Frameworks */,
25A649902CB351410015AADB /* ScopeKit in Frameworks */,
25064D392CAEFEFF00181796 /* GoogleSignIn in Frameworks */,
2569F4DB2CB8B1D3006B5D7F /* SwiftUIIntrospect in Frameworks */,
25C962D42C7B07C500EB872E /* libData.a in Frameworks */,
25064DDB2CAF862D00181796 /* SignKit in Frameworks */,
253DC2B22C7EBEAC0047C401 /* MyDesignSystem in Frameworks */,
Expand Down Expand Up @@ -284,6 +286,7 @@
25064DDA2CAF862D00181796 /* SignKit */,
25A6498F2CB351410015AADB /* ScopeKit */,
2502587F2CB3CF4700ADCF68 /* GoogleMobileAds */,
2569F4DA2CB8B1D3006B5D7F /* SwiftUIIntrospect */,
);
productName = Graduating;
productReference = 2560F1732C746C16007009E2 /* Graduating.app */;
Expand Down Expand Up @@ -409,6 +412,7 @@
25064DD92CAF862D00181796 /* XCRemoteSwiftPackageReference "SignKit" */,
25A6498E2CB351400015AADB /* XCRemoteSwiftPackageReference "ScopeKit" */,
2502587E2CB3CF4700ADCF68 /* XCRemoteSwiftPackageReference "swift-package-manager-google-mobile-ads" */,
2569F4D92CB8B1D3006B5D7F /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */,
);
productRefGroup = 2560F1742C746C16007009E2 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -956,6 +960,14 @@
kind = branch;
};
};
2569F4D92CB8B1D3006B5D7F /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/siteline/SwiftUI-Introspect";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.3.0;
};
};
25A6498E2CB351400015AADB /* XCRemoteSwiftPackageReference "ScopeKit" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/hhhello0507/ScopeKit";
Expand Down Expand Up @@ -1042,6 +1054,11 @@
package = 253DC2B02C7EBEAC0047C401 /* XCRemoteSwiftPackageReference "my-ios-kit" */;
productName = MyDesignSystem;
};
2569F4DA2CB8B1D3006B5D7F /* SwiftUIIntrospect */ = {
isa = XCSwiftPackageProductDependency;
package = 2569F4D92CB8B1D3006B5D7F /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */;
productName = SwiftUIIntrospect;
};
25A6498F2CB351410015AADB /* ScopeKit */ = {
isa = XCSwiftPackageProductDependency;
package = 25A6498E2CB351400015AADB /* XCRemoteSwiftPackageReference "ScopeKit" */;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"originHash" : "233256157ce8c7b2a459f5fd347224063374ade37589202e1db41455af6da5b7",
"originHash" : "0c9910f1ba24405814dab8bcf7fb230c658c4830992f047ecc3139924edfee87",
"pins" : [
{
"identity" : "alamofire",
Expand Down Expand Up @@ -153,6 +153,15 @@
"revision" : "74f2ec169551c3b924947b473716142a0b983e10",
"version" : "2.6.0"
}
},
{
"identity" : "swiftui-introspect",
"kind" : "remoteSourceControl",
"location" : "https://github.com/siteline/SwiftUI-Introspect",
"state" : {
"revision" : "807f73ce09a9b9723f12385e592b4e0aaebd3336",
"version" : "1.3.0"
}
}
],
"version" : 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,43 @@ extension HomeMealContainer: View {
public var body: some View {
LazyVStack(spacing: 8) {
ForEach(meals, id: \.id) { meal in
VStack(spacing: 12) {
HStack(spacing: 0) {
if let mealType = meal.mealType?.korean {
Text(mealType)
.myFont(.bodyM)
.padding(.horizontal, 12)
.padding(.vertical, 4)
.foreground(Colors.Static.white)
.background(Colors.Primary.normal)
.cornerRadius(12, corners: .allCorners)
}
Spacer()
Text("\(Int(meal.calorie)) Kcal")
.myFont(.labelM)
.foreground(Colors.Label.alternative)
}
VStack(spacing: 2) {
ForEach(Array(meal.menu.enumerated()), id: \.offset) { index, menu in
Text(menu)
.myFont(.labelR)
.foreground(Colors.Label.normal)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
MealCell(meal: meal)
}
}
}
}

struct MealCell: View {
let meal: Meal
var body: some View {
VStack(spacing: 12) {
HStack(spacing: 0) {
if let mealType = meal.mealType?.korean {
Text(mealType)
.myFont(.bodyM)
.padding(.horizontal, 12)
.padding(.vertical, 4)
.foreground(Colors.Static.white)
.background(Colors.Primary.normal)
.cornerRadius(12, corners: .allCorners)
}
Spacer()
Text("\(Int(meal.calorie)) Kcal")
.myFont(.labelM)
.foreground(Colors.Label.alternative)
}
VStack(spacing: 2) {
ForEach(Array(meal.menu.enumerated()), id: \.offset) { index, menu in
Text(menu)
.myFont(.labelR)
.foreground(Colors.Label.normal)
.frame(maxWidth: .infinity, alignment: .leading)
}
.padding(16)
.background(Colors.Background.normal)
.cornerRadius(18, corners: .allCorners)
.shadow(.evBlack1)
}
}
.padding(16)
.background(Colors.Background.normal)
.cornerRadius(18, corners: .allCorners)
.shadow(.evBlack1)
}
}
2 changes: 1 addition & 1 deletion Graduating-iOS/Graduating/Feature/Main/MainView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extension MainView: View {
MyBottomAppBar(selection: $selection) {
HomeView()
.page(icon: Icons.Feature.Home, text: "")
MealView()
MealViewa()
.page(icon: Icons.Feature.Utensils, text: "급식")
ProfileView()
.page(icon: Icons.Feature.Person, text: "프로필")
Expand Down
43 changes: 43 additions & 0 deletions Graduating-iOS/Graduating/Feature/Main/Meal/CalendarDateCell.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import SwiftUI
import Shared
import MyDesignSystem

struct CalendarDateCell: View {

private let date: Date?
private let selected: Bool

init(date: Date?, selected: Bool) {
self.date = date
self.selected = selected
}

private var label: String {
if let date {
"\(date[.day])"
} else {
""
}
}

var body: some View {
Text(label)
.myFont(.headlineM)
.foreground(
selected
? Colors.Static.white
: Colors.Label.alternative
)
.padding(.vertical, 8)
.background {
if selected {
Rectangle()
.fill(Colors.Primary.normal)
.cornerRadius(12, corners: .allCorners)
.frame(width: 36, height: 36)
}
}
.frame(maxWidth: .infinity)
.opacity(date == nil ? 0 : 1)
}
}
4 changes: 0 additions & 4 deletions Graduating-iOS/Graduating/Feature/Main/Meal/MealView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ extension MealView: View {
.refreshable {
viewModel.refresh()
}
.googleBannderAd(
inset: .top,
adUnitId: "ca-app-pub-2589637472995872/3554240467"
)
}
.onAppear {
viewModel.onAppear()
Expand Down
38 changes: 28 additions & 10 deletions Graduating-iOS/Graduating/Feature/Main/Meal/MealViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,46 @@ import Data
import Shared

public final class MealViewModel: ObservableObject {
@Published var meals: Resource<[Meal]> = .idle
var subscriptions = Set<AnyCancellable>()

@Published var meals: Resource<[Meal]> = .idle

var isFirstOnAppear: Bool = true

@Published var selectedDate: Date = .now
@Published var selectedCalendar: Date = .now

init() {
self.observe()
}
}

extension MealViewModel {
func refresh() {
fetchAllData()
}

func observe() {
self.$selectedDate.sink { _ in
self.fetchAllData()
}
.store(in: &subscriptions)
}
}

extension MealViewModel: OnAppearProtocol {
func fetchAllData() {
MealService.shared.fetchMeals()
.map {
$0.sorted {
($0.mealType?.priority ?? 0) > ($1.mealType?.priority ?? 0)
}
MealService.shared.fetchMeals(
.init(date: selectedDate)
)
.map {
$0.sorted {
($0.mealType?.priority ?? 0) > ($1.mealType?.priority ?? 0)
}
.resource(\.meals, on: self)
.ignoreError()
.silentSink()
.store(in: &subscriptions)
}
.resource(\.meals, on: self)
.ignoreError()
.silentSink()
.store(in: &subscriptions)
}
}
Loading

0 comments on commit e44da76

Please sign in to comment.