Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ final class AppointmentCreationViewController: UIViewController {
}
.store(in: &cancellables)

viewModel.$appointmentPlace
viewModel.$place
.receive(on: DispatchQueue.main)
.sink { [weak self] place in
guard let self, let place else { return }
self.creationCard.setPlaceLabel(place)
.sink { [weak self] placeInfo in
guard let self, let placeInfo else { return }
self.creationCard.setPlaceLabel(name: placeInfo.name)
}
.store(in: &cancellables)

Expand Down Expand Up @@ -198,7 +198,7 @@ extension AppointmentCreationViewController {
nearbyPlaceRepository: MockNearbyPlaceRepository(),
reverseGeocodingRepository: MockReverseGeocodingRepository()
),
initialCoordinate: viewModel.appointmentPlace?.coordinate
initialCoordinate: viewModel.place?.coordinate
)
let placeSelectionViewController = PlaceSelectionViewController(viewModel: placeSelectionViewModel)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ final class AppointmentCreationViewModel {
private var id: String?
private var code: String?
private var isCreating = false
private var placeDomain: Place?

@Published private(set) var appointmentDate: Date?
@Published private(set) var appointmentPlace: Place?
@Published private(set) var place: PlaceInfo?
@Published private(set) var hasCreated: Bool = false

init(createAppointmentUseCase: CreateAppointmentUseCase) {
Expand All @@ -35,7 +36,8 @@ final class AppointmentCreationViewModel {
}

func setPlace(_ place: Place) {
appointmentPlace = place
placeDomain = place
self.place = PlaceInfo(place: place)
}

func create() {
Expand All @@ -46,7 +48,7 @@ final class AppointmentCreationViewModel {
createAppointmentUseCase.execute(
title: appointmentTitle,
date: appointmentDate,
place: appointmentPlace
place: placeDomain
) { [weak self] result in
guard let self else { return }
DispatchQueue.main.async {
Expand All @@ -70,13 +72,7 @@ final class AppointmentCreationViewModel {
code: code ?? "",
title: appointmentTitle,
date: appointmentDate,
location: appointmentPlace.map {
AppointmentLocation(
title: $0.name,
address: $0.address,
coordinate: $0.coordinate
)
},
location: placeDomain.map { AppointmentLocation(place: $0) },
participants: []
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ final class AppointmentCreateCard: UIView {
fieldsBox.dateText = date.appointmentDateTimeText
}

func setPlaceLabel(_ place: Place) {
fieldsBox.placeText = place.name
func setPlaceLabel(name: String) {
fieldsBox.placeText = name
}

private func setUp() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ final class AppointmentInfoViewModel {
fetchAppointmentInfoUseCase.execute(appointmentID: appointmentID) { [weak self] result in
DispatchQueue.main.async {
if case .success(let appointment) = result {
self?.appointmentInfo = self?.buildAppointmentInfo(from: appointment)
self?.appointmentInfo = AppointmentInfo(appointment: appointment)
}
}
}
Expand Down Expand Up @@ -58,27 +58,10 @@ final class AppointmentInfoViewModel {
) { [weak self] result in
DispatchQueue.main.async {
if case .success(let appointment) = result {
self?.appointmentInfo = self?.buildAppointmentInfo(from: appointment)
self?.appointmentInfo = AppointmentInfo(appointment: appointment)
}
}
}
}

private func buildAppointmentInfo(from appointment: Appointment) -> AppointmentInfo {
let location = appointment.place.map {
AppointmentLocation(title: $0.name, address: $0.address, coordinate: $0.coordinate)
}
let participants = appointment.participants.map {
Participant(id: $0.id, nickname: $0.nickname, profileImage: $0.profileImage.lastPathComponent)
}
return AppointmentInfo(
id: appointment.id,
code: appointment.code,
title: appointment.name,
date: appointment.dateTime,
location: location,
participants: participants
)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ private extension ChatViewModel {
id: message.id,
senderID: message.sender.id,
senderNickname: message.sender.nickname,
senderProfileImage: message.sender.profileImage.lastPathComponent,
senderProfileImage: message.sender.profileImageName,
content: bubbleContent,
timeText: timeText,
sentAt: message.sentAt,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,8 @@ final class SharedPlacesViewModel {
}

private func buildItems() {
var result = sharedPlaces.map { shared in
SharedPlaceItem(
id: shared.id,
placeName: shared.place.name,
placeAddress: shared.place.address,
voterProfileImages: shared.voters.map { $0.profileImage.lastPathComponent },
hasVoted: shared.voters.contains { $0.id == currentUserID },
sharedAt: shared.sharedAt
)
var result = sharedPlaces.map {
SharedPlaceItem(sharedPlace: $0, currentUserID: currentUserID)
}

switch sortOrder {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,7 @@ final class SearchPlaceCardViewController: UIViewController {
viewModel.$filteredPlaces
.receive(on: DispatchQueue.main)
.sink { [weak self] places in
let infos = places.map {
PlaceInfo(id: $0.id, name: $0.name, address: $0.address, tag: $0.type)
}
self?.searchCard.updatePlaces(infos)
self?.searchCard.updatePlaces(places)
}
.store(in: &cancellables)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Combine

final class SearchPlaceCardViewModel {

@Published private(set) var filteredPlaces: [Place] = []
@Published private(set) var filteredPlaces: [PlaceInfo] = []
@Published private(set) var selectedFilters: [PlaceType] = []
@Published private(set) var isSearching = false
@Published private(set) var hasSearched = false
Expand Down Expand Up @@ -63,11 +63,13 @@ final class SearchPlaceCardViewModel {
}

private func applyFilter() {
let filtered: [Place]
if selectedFilters.isEmpty {
filteredPlaces = allPlaces
filtered = allPlaces
} else {
filteredPlaces = allPlaces.filter { selectedFilters.contains($0.type) }
filtered = allPlaces.filter { selectedFilters.contains($0.type) }
}
filteredPlaces = filtered.map { PlaceInfo(place: $0) }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ extension FilterTagBox {

init(placeType: PlaceType) {
self.placeType = placeType
self.capsule = PlaceTagCapsule(placeType)
self.capsule = PlaceTagCapsule(title: placeType.title, color: placeType.color.uiColor)
super.init(frame: .zero)
setUp()
}
Expand Down Expand Up @@ -168,7 +168,7 @@ extension FilterTagBox {

private func updateAppearance() {
let baseColor: UIColor = isSelected
? placeType.color
? placeType.color.uiColor
: UIColor.systemGray2.withAlphaComponent(0.3)
capsule.setColor(isHighlighted ? baseColor.withAlphaComponent(0.6) : baseColor)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ final class PlaceCell: UIView {
private let selectionButton: UIButton

init(_ place: PlaceInfo, buttonText: String) {
self.placeTag = PlaceTagCapsule(place.tag)
self.placeTag = PlaceTagCapsule(title: place.tagTitle, color: place.tagColor.uiColor)
self.selectionButton = UIButton.filled(
title: buttonText,
background: .blue2.withAlphaComponent(0.85),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ final class PlaceTagCapsule: UIView {
return label
}()

init(_ placeType: PlaceType) {
init(title: String, color: UIColor) {
super.init(frame: .zero)
label.text = placeType.title
setUp(backgroundColor: placeType.color)
label.text = title
setUp(backgroundColor: color)
}

required init?(coder: NSCoder) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// ColorAsset+UIColor.swift
// WhereAreYou
//
// Created by 이상유 on 2026-08-18.
//

import UIKit

extension ColorAsset {

var uiColor: UIColor {
switch self {
case .green: return .systemGreen
case .yellow: return .systemYellow
case .orange: return .orange
case .indigo: return .systemIndigo
case .blue: return .systemBlue
case .red: return .systemRed
case .brown: return .systemBrown
}
}

}
16 changes: 8 additions & 8 deletions WhereAreYou/WhereAreYou/Presentation/Extension/PlaceType+.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by 이상유 on 2026-07-16.
//

import UIKit
import Foundation

extension PlaceType {

Expand All @@ -21,15 +21,15 @@ extension PlaceType {
}
}

var color: UIColor {
var color: ColorAsset {
switch self {
case .subway: return .systemGreen
case .restaurant: return .systemYellow
case .subway: return .green
case .restaurant: return .yellow
case .cafe: return .orange
case .hospital: return .systemIndigo
case .station: return .systemBlue
case .shop: return .systemRed
case .other: return .systemBrown
case .hospital: return .indigo
case .station: return .blue
case .shop: return .red
case .other: return .brown
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by 이상유 on 2026-07-14.
//

import UIKit
import Foundation

extension TransportType {

Expand All @@ -25,11 +25,11 @@ extension TransportType {
}
}

var color: UIColor {
var color: ColorAsset {
switch self {
case .walk: return .systemGreen
case .car: return .systemIndigo
case .transit: return .systemYellow
case .walk: return .green
case .car: return .indigo
case .transit: return .yellow
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// User+ProfileImage.swift
// WhereAreYou
//
// Created by 이상유 on 2026-08-17.
//

import Foundation

extension User {

/// 프로필 이미지 URL에서 화면에 사용할 에셋 이름만 추출
/// - 서버 연동 후 이미지 표현이 바뀌면 이 프로퍼티 한 곳만 수정하면 된다.
var profileImageName: String {
profileImage.lastPathComponent
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ final class AppointmentRouteInfoView: UIView {
routeSummaryCard.setRemaining(timeText: timeText)
}

func setSteps(_ steps: [RouteStep]) {
func setSteps(_ steps: [RouteStepItem]) {
routeSummaryCard.setSteps(steps)
}

Expand Down Expand Up @@ -225,7 +225,7 @@ private final class RouteSummaryCardView: UIView {
remainingTimeSummary.valueLabel.text = timeText
}

func setSteps(_ steps: [RouteStep]) {
func setSteps(_ steps: [RouteStepItem]) {
stepLabelsStack.arrangedSubviews.forEach { $0.removeFromSuperview() }
stepBarsStack.arrangedSubviews.forEach { $0.removeFromSuperview() }
stepBarWidthConstraints.forEach { $0.isActive = false }
Expand All @@ -236,18 +236,18 @@ private final class RouteSummaryCardView: UIView {

guard !steps.isEmpty else { return }

let totalTime = max(steps.reduce(0) { $0 + $1.estimatedTime }, 1)
let totalTime = max(steps.reduce(0) { $0 + $1.estimatedTimeMinutes }, 1)

for step in steps {
let icon = UIImageView(image: UIImage(systemName: step.transportType.icon))
icon.tintColor = step.transportType.color
let icon = UIImageView(image: UIImage(systemName: step.transportIcon))
icon.tintColor = step.transportColor.uiColor
icon.contentMode = .scaleAspectFit
icon.translatesAutoresizingMaskIntoConstraints = false
icon.widthAnchor.constraint(equalToConstant: 14).isActive = true
icon.heightAnchor.constraint(equalToConstant: 14).isActive = true

let label = UILabel()
label.text = "\(Int(step.estimatedTime))분"
label.text = "\(Int(step.estimatedTimeMinutes))분"
label.font = .preferredFont(forTextStyle: .caption2)
label.textColor = .secondaryLabel

Expand All @@ -258,7 +258,7 @@ private final class RouteSummaryCardView: UIView {
stepLabelsStack.addArrangedSubview(labelStack)

let bar = UIView()
bar.backgroundColor = step.transportType.color
bar.backgroundColor = step.transportColor.uiColor
bar.layer.cornerRadius = 2
bar.heightAnchor.constraint(equalToConstant: 4).isActive = true
stepBarsStack.addArrangedSubview(bar)
Expand All @@ -271,7 +271,7 @@ private final class RouteSummaryCardView: UIView {

let minWidth = labelStack.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).width
stepMinWidths.append(minWidth)
stepRatios.append(CGFloat(step.estimatedTime / totalTime))
stepRatios.append(CGFloat(step.estimatedTimeMinutes / totalTime))
}

setNeedsLayout()
Expand Down
Loading
Loading