-
Notifications
You must be signed in to change notification settings - Fork 120
[Woo POS] Coupons: Enable site coupons when tap on CTA #15478
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WooCommerce/Classes/POS/Presentation/PointOfSaleDashboardView.swift
Outdated
Show resolved
Hide resolved
|
|
staskus
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
I left the logic about the dashboard view state.
Could you create the remaining tasks in Linear so we wouldn't miss any details to properly implement error, empty, and disabled states according to the designs and with the localized copy?
WooCommerce/Classes/POS/Presentation/PointOfSaleDashboardView.swift
Outdated
Show resolved
Hide resolved
WooCommerce/Classes/POS/Presentation/PointOfSaleDashboardView.swift
Outdated
Show resolved
Hide resolved
|
@iamgabrielma I suggest checking, reviewing, testing, and merging [Woo POS] Restore checkStoreCouponSettings to PointOfSaleCouponService before proceeding to avoid additional conflicts. Also worth considering consistent place to call settings. We do it within |
Sounds good, I'll do that first as otherwise working on this one will become messy, then apply your suggestions.
Sure, I see you've already created these, I've added WOOMOB-253 so we don't forget to localize, or I'll do it just here when addressing the rest of changes. |
staskus
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Looks good 👍
It would be good to add a couple of missing pieces so the solution would be full and only UI missing:
- Handle in controller when service fails to enable coupons
- Add tests
Thanks 👍
|
|
||
|
|
||
| @available(iOS 17.0, *) | ||
| extension PointOfSaleItemsControllerProtocol { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this extension with default implementation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do unfortunately, since we need to call couponsController.enableCoupons() in the aggregate, and this is a specialization of couponsController PointOfSaleItemsControllerProtocol
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I didn't realize that at first. I don't love that ItemController gets affected this way.
This is what we could do:
- Create
PointOfSaleCouponsControllerProtocolwhich extendsPointOfSaleItemsControllerProtocol:
protocol PointOfSaleCouponsControllerProtocol: PointOfSaleItemsControllerProtocol {
/// Enables coupons in store settings, if needed
func enableCoupons() async
}
-
Implement it
final class PointOfSaleCouponsController: PointOfSaleCouponsControllerProtocol -
Use it in aggregate model:
private let couponsController: PointOfSaleCouponsControllerProtocol -
Profit
This way coupons controller can still share common funtionality with items controller but also grow with additional coupons related functionality.
# Conflicts: # WooCommerce/Classes/POS/Controllers/PointOfSaleItemsController.swift # WooCommerce/Classes/POS/Presentation/PointOfSaleDashboardView.swift
|
👋 I'll need to iterate on the approach we took here, as with the changes on the controller and item view state we've recently merged this use case doesn't work anymore: From what I've checked so far, when switching to coupons, and coupons throw the |
Issue seems to be here, since we do not use a "current controller", when we render the dashboard we're only checking for changes in the "item controller" which not really an item controller but a product controller, changes on |
When view state changed, driven by changes in coupons, these were never propagated to the dashboard view since we only switched in “itemsViewState” which only covered the products controller.
|
Thanks for the review again @staskus It seems we still need to expose some sort of "current" controller or view state to the views from the aggregate, otherwise we were only publishing changes in the "product view state", not on the coupons view state.I've added this on 562c1c1 I've also added some minimal renaming for "items", and named them "products". Otherwise gets very confusing to work with these lists and state and be sure what its actually updating, and one of the reasons we missed this issue originally (we're calling "items" to products, and calling "items" to items). I think we still need to rename this further across the board, but we can do this separately. Xcode has decided today that doesn't want to compile the tests locally (I've cleared derived data a few times, and rebuilt, but is not very useful) but they're passing CI. If you're ok with this I'll add the tests separately, for now I'll leave this PR for review to move the ball forward as I'm EOD:
|
| .trackSize(size: $floatingSize) | ||
| .accessibilitySortPriority(1) | ||
| .renderedIf(posModel.itemsViewState.containerState != .loading) | ||
| .renderedIf(posModel.currentViewState.containerState != .loading) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This took me a while: By leaving this one as posModel.itemViewstate, when switching to Coupons we were always stuck in .loading state, not showing coupons correctly. Of course the compiler didn't complain, but was tricky to find why the view state was wrong. I think we can move those ones to some computed property, or grab them directly from reading a variable from the aggregate model.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, this containerState logic doesn't work for products and coupons anymore, since we don't want to be showing coupons errors in full screen. This structure may change 🤔
staskus
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! I understand the need for currentViewState 👍 , I think we could go this way but leave only one source of truth.
Also, I noticed that when coupons enabled, products tab is opened. Coupons tab should still be selected:
loading.switches.to.products.mp4
| func trackCardPaymentsOnboardingShown() | ||
|
|
||
| var itemsViewState: ItemsViewState { get } | ||
| var productsViewState: ItemsViewState { get } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I encourage not to make this renaming unless we rename all the items to products in the codebase.
As far as our internal codebase and business case knowledge goes - items include products and product variations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha, I've reverted it on e1979c9 I still think we should rename this at some point across the codebase as coupons should be considered items as well in certain layers.
|
|
||
| @available(iOS 17.0, *) | ||
| @Observable final class PointOfSaleItemsController: PointOfSaleSearchingItemsControllerProtocol { | ||
| @Observable final class PointOfSaleItemsController: PointOfSaleItemsControllerProtocol, PointOfSaleSearchingItemsControllerProtocol { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PointOfSaleSearchingItemsControllerProtocol extends PointOfSaleItemsControllerProtocol, no need to add it again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed! f7db770
| .trackSize(size: $floatingSize) | ||
| .accessibilitySortPriority(1) | ||
| .renderedIf(posModel.itemsViewState.containerState != .loading) | ||
| .renderedIf(posModel.currentViewState.containerState != .loading) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, this containerState logic doesn't work for products and coupons anymore, since we don't want to be showing coupons errors in full screen. This structure may change 🤔
| @available(iOS 17.0, *) | ||
| extension PointOfSaleAggregateModel { | ||
| func updateCurrentViewState(base: ItemListBaseItem) { | ||
| let viewState = base.itemType == .products ? productsViewState : couponsViewState |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If currentViewState is required, I wonder if we should approach it differently.
ItemListView already holds selectedItemType. Maybe we should track selection in a single place—an aggregate model? That would give a source of truth and allows to keep currentViewState and even currentController as computed helper variables.
ItemListView also doesn't need to switch for itemsStack anymore and can use posModel.currentViewState.itemsStack.
Wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think so. This also should help to keep proper state on which tabs we should be loading (products v coupons) when something from outside the list view happens (eg: errors, retry, etc, ... ). I've logged this on WOOMOB-269
|
|
||
|
|
||
| @available(iOS 17.0, *) | ||
| extension PointOfSaleItemsControllerProtocol { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I didn't realize that at first. I don't love that ItemController gets affected this way.
This is what we could do:
- Create
PointOfSaleCouponsControllerProtocolwhich extendsPointOfSaleItemsControllerProtocol:
protocol PointOfSaleCouponsControllerProtocol: PointOfSaleItemsControllerProtocol {
/// Enables coupons in store settings, if needed
func enableCoupons() async
}
-
Implement it
final class PointOfSaleCouponsController: PointOfSaleCouponsControllerProtocol -
Use it in aggregate model:
private let couponsController: PointOfSaleCouponsControllerProtocol -
Profit
This way coupons controller can still share common funtionality with items controller but also grow with additional coupons related functionality.
|
I've split the feedback between changes I'm doing in this one vs changes we can follow-up with on different issues, so I can scope this one, as the protocol changes come with updates to ~30 files and can get messy: Changes:
To do:
|
Just to add: At some point it worked well, but then I could replicate the issue every time I've tried. I think once we make further changes regarding handling the view correctly (not full-screen) and move the source of truth of selected item somewhere else it should be either resolved or easier to resolve. For now is logged on WOOMOB-268 Screen.Recording.2025-04-08.at.17.59.31.mov |
staskus
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the fixes and creating additional tasks. 👍
I think we took this task too early, or tried to achieve too much with this PR. We really needed an infrastructure of showing a state within the list to properly tackle this. Now, we have to merge half-baked happy and unhappy paths.


Closes: #15348
Description
This PR adds the ability of enabling the site's coupons when we tap the CTA. At the moment we're still using the full-screen error view to handle loading errors for products and coupons, but from the latests designs it seems we'll be moving to a partial screen (pdfdoF-6PX#comment-7945-p2) so I focused on the functionality and reusing the error view over the UI details.
Screen.Recording.2025-04-03.at.13.56.36.mov
Testing information
Enable, wait a moment (loading state to be handled)RELEASE-NOTES.txtif necessary.Reviewer (or Author, in the case of optional code reviews):
Please make sure these conditions are met before approving the PR, or request changes if the PR needs improvement: