-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Conversation
27e25d1
to
66e0ab6
Compare
client/web/src/cody/management/subscription/manage/PaymentDetails.tsx
Outdated
Show resolved
Hide resolved
client/web/src/cody/management/subscription/manage/PaymentDetails.tsx
Outdated
Show resolved
Hide resolved
client/web/src/cody/management/subscription/new/CodyProCheckoutForm.tsx
Outdated
Show resolved
Hide resolved
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.
Plan state management becomes complex. To simplify it, I think we should consider the following.
1. Move the plan value calculation and plan changes logic into a custom hook.
For example:
type CodyPlanHookArgs = any // whatever we need to set it up properly
type CodyPlanHook = (...args: CodyPlanHookArgs) => {
// referencing the existing interface, not sure whether it correctly reflects its content
plan: TeamSizeChange;
// 🤞🏻 maybe we can even encapsulate initial seat count login in a hook and won't need to expose it
initialSeatCount: number;
// some indicator of whether the returned plan is up to date, e.g.
status: 'success' | 'pending' | 'error';
previewSeatCountChange: (diff: number) => void;
updateSubscriptionPlan: () => void;
}
The core returned value here is plan
(or however we name it). It can be computed based either on local state (if addSeats
if false
) or on the server state (if we need to get data from the payment system before).
The hook may also return additional fields and methods. The main idea is to hide as many seat/price calculation details as possible. Currently, they are spread across quite a big component.
2. Keep state as minimal as possible.
We should avoid duplication and redundant state where possible. If we can calculate some information from the component’s props or its existing state variables during rendering, we should not put that information into that component’s state (from docs). E.g., monthlyPriceDiff
, newMonthlyPrice
, dueNow
can be computed from the seats count and price per seat.
3. Preview current subscription update may be a query, not a mutation.
Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects.
From docs.
previewUpdateCurrentSubscriptionMutation
doesn't seem to change anything, it defers to backend to request a new price from the payment system.
I'm not 100% sure about it, as I haven't tried to implement it, but it looks to me more like a query that depends on addSeats
and seatCountDiff
variables.
**4. Use mutations "conventionally".
Having to look for workarounds like mutateAsync.call()
hints that we may overcomplicate the way we use React Query mutations. Can we call mutation from an event handler and then derive the needed UI based on the mutation state?
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 think this is a very valid suggestion but want to move fast, so I've created an issue to track this improvement: https://github.com/sourcegraph/sourcegraph/issues/63349
client/web/src/cody/management/subscription/new/CodyProCheckoutForm.tsx
Outdated
Show resolved
Hide resolved
client/web/src/cody/management/subscription/new/CodyProCheckoutForm.tsx
Outdated
Show resolved
Hide resolved
client/web/src/cody/management/subscription/new/CodyProCheckoutForm.tsx
Outdated
Show resolved
Hide resolved
client/web/src/cody/management/subscription/new/NewCodyProSubscriptionPage.tsx
Show resolved
Hide resolved
client/web/src/cody/management/subscription/new/NewCodyProSubscriptionPage.tsx
Outdated
Show resolved
Hide resolved
client/web/src/cody/management/subscription/new/NewCodyProSubscriptionPage.tsx
Outdated
Show resolved
Hide resolved
client/web/src/cody/management/subscription/PaymentMethodPreview.tsx
Outdated
Show resolved
Hide resolved
- Load subscription data - Remove "team" query param to simplify the interface - Improve error handling and display - Fix: Make sure the initial seat count is within valid boundaries - Add price preview UI (without data preview)
Tested it, it works!
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.
Approving to unblock. Feel free to address any comments in this or subsequent PRs as you see fit.
To code reviewers: This PR consists of 15 commits already, but I'd say it still might be worth going commit by commit because I managed to use almost atomic commits throughout the development. There were unfortunately a few cases where I didn't use the right naming for some entities at first, and as a result, there is a bit of back-and-forth through the commits, but I think it's still relatively easy to follow.
The changes in this PR:
seats=2000
, the form initialized with 2000. Now it does with 50, as the max seat count.CodyProCheckoutForm
component started being quite complex.Test plan
Manual QA. I clicked through it a few times, and it worked well. Here is a 5-minute Loom where I demo the whole team creation and seat adjustment flows.