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
6 changes: 3 additions & 3 deletions WooCommerce/Classes/ViewRelated/Dashboard/DashboardView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct DashboardView: View {
/// Set externally in the hosting controller.
var onboardingTaskTapped: ((Site, StoreOnboardingTask) -> Void)?
/// Set externally in the hosting controller.
var viewAllOnboardingTasksTapped: ((Site) -> Void)?
var viewAllOnboardingTasksTapped: ((Site, [StoreOnboardingTaskViewModel]) -> Void)?

/// Set externally in the hosting controller.
var showAllBlazeCampaignsTapped: (() -> Void)?
Expand Down Expand Up @@ -215,9 +215,9 @@ private extension DashboardView {
onTaskTapped: { task in
guard let currentSite else { return }
onboardingTaskTapped?(currentSite, task)
}, onViewAllTapped: {
}, onViewAllTapped: { tasks in
guard let currentSite else { return }
viewAllOnboardingTasksTapped?(currentSite)
viewAllOnboardingTasksTapped?(currentSite, tasks)
})
case .blaze:
BlazeCampaignDashboardView(viewModel: viewModel.blazeCampaignDashboardViewModel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,11 @@ private extension DashboardViewHostingController {
storeOnboardingCoordinator?.start(task: task)
}

rootView.viewAllOnboardingTasksTapped = { [weak self] site in
rootView.viewAllOnboardingTasksTapped = { [weak self] site, tasks in
guard let self else { return }
ServiceLocator.analytics.track(event: .DynamicDashboard.dashboardCardInteracted(type: .onboarding))
updateStoreOnboardingCoordinatorIfNeeded(with: site)
storeOnboardingCoordinator?.start()
storeOnboardingCoordinator?.start(tasks: tasks)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import struct Yosemite.Site
import struct Yosemite.StoreOnboardingTask

/// Coordinates navigation for store onboarding.
final class StoreOnboardingCoordinator: Coordinator {
final class StoreOnboardingCoordinator {
typealias TaskType = StoreOnboardingTask.TaskType

let navigationController: UINavigationController
Expand All @@ -31,11 +31,15 @@ final class StoreOnboardingCoordinator: Coordinator {
}

/// Navigates to the fullscreen store onboarding view.
func start() {
func start(tasks: [StoreOnboardingTaskViewModel]) {
Task { @MainActor in
let viewModel = StoreOnboardingViewModel(
siteID: site.siteID,
isExpanded: true,
taskViewModels: tasks
)
let onboardingNavigationController = UINavigationController()
let onboardingViewController = StoreOnboardingViewHostingController(viewModel: .init(siteID: site.siteID,
isExpanded: true),
let onboardingViewController = StoreOnboardingViewHostingController(viewModel: viewModel,
navigationController: onboardingNavigationController,
site: site)
onboardingNavigationController.pushViewController(onboardingViewController, animated: false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ final class StoreOnboardingViewHostingController: SelfSizingHostingController<St
}

if !viewModel.isExpanded {
rootView.viewAllTapped = { [weak self] in
rootView.viewAllTapped = { [weak self] tasks in
guard let self else { return }
self.coordinator.start()
self.coordinator.start(tasks: tasks)
}
}
}
Expand Down Expand Up @@ -93,13 +93,13 @@ struct StoreOnboardingView: View {
/// Set externally in the hosting controller.
var taskTapped: ((StoreOnboardingTask) -> Void)?
/// Set externally in the hosting controller.
var viewAllTapped: (() -> Void)?
var viewAllTapped: (([StoreOnboardingTaskViewModel]) -> Void)?

@ObservedObject private var viewModel: StoreOnboardingViewModel

init(viewModel: StoreOnboardingViewModel,
onTaskTapped: ((StoreOnboardingTask) -> Void)? = nil,
onViewAllTapped: (() -> Void)? = nil) {
onViewAllTapped: (([StoreOnboardingTaskViewModel]) -> Void)? = nil) {
self.viewModel = viewModel
self.taskTapped = onTaskTapped
self.viewAllTapped = onViewAllTapped
Expand Down Expand Up @@ -159,7 +159,9 @@ struct StoreOnboardingView: View {
.padding(.leading, Layout.padding)

// View all button
viewAllButton(action: viewAllTapped, text: String(format: Localization.viewAll, viewModel.taskViewModels.count))
viewAllButton(action: {
viewAllTapped?(viewModel.taskViewModels)
}, text: String(format: Localization.viewAll, viewModel.taskViewModels.count))
.renderedIf(viewModel.shouldShowViewAllButton)
.padding(.horizontal, Layout.padding)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class StoreOnboardingViewModel: ObservableObject {
/// - defaults: UserDefaults for storing when all onboarding tasks are completed
init(siteID: Int64,
isExpanded: Bool,
taskViewModels: [StoreOnboardingTaskViewModel] = [],
stores: StoresManager = ServiceLocator.stores,
defaults: UserDefaults = .standard,
analytics: Analytics = ServiceLocator.analytics,
Expand All @@ -94,6 +95,7 @@ class StoreOnboardingViewModel: ObservableObject {
self.defaults = defaults
self.analytics = analytics
self.waitingTimeTracker = waitingTimeTracker
self.taskViewModels = taskViewModels

$noTasksAvailableForDisplay
.combineLatest(defaults.publisher(for: \.completedAllStoreOnboardingTasks))
Expand All @@ -117,7 +119,11 @@ class StoreOnboardingViewModel: ObservableObject {
}

analytics.track(event: .DynamicDashboard.cardLoadingStarted(type: .onboarding))
update(state: .loading)
if taskViewModels.isEmpty {
update(state: .loading)
} else {
update(state: .loaded(rows: taskViewModels))
}

let tasks: [StoreOnboardingTaskViewModel]
var syncingError: Error?
Expand Down
74 changes: 64 additions & 10 deletions WooCommerce/Resources/ar.lproj/Localizable.strings
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Translation-Revision-Date: 2025-11-03 19:54:06+0000 */
/* Translation-Revision-Date: 2025-11-17 16:54:04+0000 */
/* Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5; */
/* Generator: GlotPress/2.4.0-alpha */
/* Language: ar */
Expand Down Expand Up @@ -797,7 +797,13 @@ which should be translated separately and considered part of this sentence. */
"BookingAttendanceStatus.booked" = "اكتمل الحجز";

/* Title for 'Cancelled' booking attendance status. */
"BookingAttendanceStatus.cancelled" = "اكتمل الإلغاء";
"BookingAttendanceStatus.canceled" = "مُلغى";

/* Title for 'Checked In' booking attendance status. */
"BookingAttendanceStatus.checkedIn" = "نجح تسجيل الحضور";

/* Title for 'No Show' booking attendance status. */
"BookingAttendanceStatus.noShow" = "عدم الحضور";

/* Title for 'Unknown' booking attendance status. */
"BookingAttendanceStatus.unknown" = "غير معروف";
Expand Down Expand Up @@ -830,26 +836,38 @@ which should be translated separately and considered part of this sentence. */
"BookingDetailsView.attendance.headerTitle" = "الحضور";

/* Content of error presented when updating the attendance status of a Booking fails. It reads: Unable to change status of Booking #{Booking number}. Parameters: %1$d - Booking number */
"BookingDetailsView.attendanceStatus.updateFailed.message" = "يتعذر تغيير حالة حضور الحجز رقم ⁦%1$d⁩";
"BookingDetailsView.attendanceStatus.failureMessage." = "يتعذر تغيير حالة حضور الحجز رقم⁦%1$d⁩.";

/* Add a booking note section in booking details view. */
"BookingDetailsView.bookingNote.addNoteRow.title" = "إضافة ملحوظة";

/* Add a note row title in booking notes section in booking details view. */
"BookingDetailsView.bookingNotes.addANoteRow.title" = "إضافة ملاحظة";
/* Footer text for the `Booking note` section in the booking details screen. */
"BookingDetailsView.bookingNote.footerText" = "هذه ملحوظة خاصة. لن نشاركها مع العميل.";

/* Header title for the 'Booking notes' section in the booking details screen. */
"BookingDetailsView.bookingNotes.headerTitle" = "ملاحظات الحجز";
/* Header title for the 'Booking note' section in the booking details screen. */
"BookingDetailsView.bookingNote.headerTitle" = "ملحوظة الحجز";

/* Title of navigation bar when editing a booking note. */
"BookingDetailsView.bookingNote.navbar.title" = "ملحوظة الحجز";

/* Cancel button title for the booking cancellation confirmation alert. */
"BookingDetailsView.cancelation.alert.cancelAction" = "لا، الاحتفاظ بالحجز";

/* Confirm button title for the booking cancellation confirmation alert. */
"BookingDetailsView.cancelation.alert.confirmAction" = "نعم، إلغاء الحجز";

/* Generic message for the booking cancellation confirmation alert. */
"BookingDetailsView.cancelation.alert.genericMessage" = "هل أنت متأكد من رغبتك في إلغاء هذا الحجز؟";

/* Message for the booking cancellation confirmation alert. %1$@ is customer name, %2$@ is product name, %3$@ is booking date. */
"BookingDetailsView.cancelation.alert.message" = "لن يتمكن %1$@ من حضور \"%2$@\" في %3$@ بعد الآن.";

/* Title for the booking cancellation confirmation alert. */
"BookingDetailsView.cancelation.alert.title" = "إلغاء الحجز";

/* Content of error presented when cancelling a Booking fails. It reads: Unable to cancel Booking #{Booking number}. Parameters: %1$d - Booking number */
"BookingDetailsView.cancellation.failureMessage" = "يتعذر إلغاء الحجز رقم⁦%1$d⁩.";

/* Billing address row title in customer section in booking details view. */
"BookingDetailsView.customer.billingAddress.title" = "عنوان الفوترة";

Expand All @@ -865,6 +883,9 @@ which should be translated separately and considered part of this sentence. */
/* 'Status' row title in attendance section in booking details view. */
"BookingDetailsView.customer.status.title" = "الحالة";

/* Content of error presented when cancelling a Booking fails. It reads: Unable to mark Booking #{Booking number} as paid. Parameters: %1$d - Booking number */
"BookingDetailsView.markAsPaid.failureMessage" = "يتعذر وضع علامة على الحجز رقم⁦%1$d⁩ على أنه مدفوع.";

/* Booking Details screen nav bar title. %1$d is a placeholder for the booking ID. */
"BookingDetailsView.navTitle" = "الحجز رقم ⁦%1$d⁩";

Expand All @@ -883,9 +904,6 @@ which should be translated separately and considered part of this sentence. */
/* Header title for the 'Payment' section in the booking details screen. */
"BookingDetailsView.payment.headerTitle" = "الدفع";

/* Title for 'Issue refund' button in payment section in booking details view. */
"BookingDetailsView.payment.issueRefund.title" = "نشر مبلغ الاسترداد";

/* Title for 'Mark as paid' button in payment section in booking details view. */
"BookingDetailsView.payment.markAsPaid.title" = "وضع علامة كـ \"مدفوع\"";

Expand Down Expand Up @@ -3555,6 +3573,18 @@ If your translation of that term also happens to contains a hyphen, please be su
/* Trash Action Spoken hint */
"Moves the comment to Trash" = "ينقل التعليق إلى سلة المهملات";

/* Cancel button title for the discard changes confirmation dialog in the multiline text editor. */
"MultilineEditableTextDetailView.discardChanges.alert.cancelAction" = "إلغاء";

/* Destructive action button title to discard changes in the multiline text editor. */
"MultilineEditableTextDetailView.discardChanges.alert.discardAction" = "تجاهل التغييرات";

/* Title for the confirmation dialog when the user attempts to discard changes in the multiline text editor. */
"MultilineEditableTextDetailView.discardChanges.alert.title" = "هل أنت متأكد من رغبتك في تجاهل هذه التغييرات؟";

/* Navigation bar button title used to save changes and close the multiline text editor. */
"MultilineEditableTextDetailView.doneButton.title" = "تم";

/* Title of multiple stores as part of Jetpack benefits. */
"Multiple Stores" = "متاجر متعددة";

Expand Down Expand Up @@ -4569,6 +4599,9 @@ If your translation of that term also happens to contains a hyphen, please be su
/* Description of the subscription conditions for a subscription product, with signup fees but no trial.Reads as: '$25.00 signup'. */
"ProductRowViewModel.formattedProductSubscriptionConditionsWithoutTrial" = "التسجيل في %1$@";

/* Bookable product type label interpretation as Service. Presented in product type picker in filters. */
"ProductType.service" = "الخدمة";

/* Display label for the composite product's component option type
Product section title if there is more than one product.
Product section title in Review Order screen if there is more than one product.
Expand Down Expand Up @@ -7470,6 +7503,9 @@ If your translation of that term also happens to contains a hyphen, please be su
/* Label displayed on audio media items. */
"audio" = "صوت";

/* Button to dismiss a web view */
"authenticatableWebView.done" = "تم";

/* Title for the link for site creation guide. */
"authenticationConstants.siteCreationGuideButtonTitle" = "هل تريد بدء متجر جديد؟";

Expand Down Expand Up @@ -8410,9 +8446,27 @@ If your translation of that term also happens to contains a hyphen, please be su
/* Title of the booking list view */
"bookingListView.view.title" = "الحجوزات";

/* Status of a paid booking */
"bookingPaymentStatus.title.paid" = "مدفوع";

/* Status of a refunded booking */
"bookingPaymentStatus.title.refunded" = "نجح استرداد المبلغ";

/* Status of a booking with unexpected payment status */
"bookingPaymentStatus.title.unknown" = "غير معروف";

/* Status of an unpaid booking */
"bookingPaymentStatus.title.unpaid" = "غير مدفوعة";

/* Message on the empty search result view of the booking service/event selector view */
"bookingServiceEventSelectorView.emptySearchDescription" = "حاول ضبط مصطلح البحث الخاص بك لرؤية مزيد من النتائج";

/* Text on the empty view of the booking service/event selector view */
"bookingServiceEventSelectorView.noMembersFound" = "تعذر العثور على خدمة أو حدث";

/* Prompt in the search bar of the booking service/event selector view */
"bookingServiceEventSelectorView.searchPrompt" = "البحث عن الخدمة \/ الحدث";

/* Title of the booking service/event selector view */
"bookingServiceEventSelectorView.title" = "الخدمة \/ الحدث";

Expand Down
Loading
Loading