fix(server): member loading (#15156)

#### PR Dependency Tree


* **PR #15156** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Fixed Stripe subscription syncing for Team plans to update the correct
existing local subscription (avoiding duplicates) while refreshing
quantity and billing/trial period details.
* **UI/UX Improvements**
* Improved workspace member list loading/error states with shared UI
components and steadier pagination behavior.
  * Refined fallback styling for cleaner, more stable layout.
* **Tests**
* Expanded subscription and projection coverage and adjusted
seat-allocation/e2e assertions to be more robust.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2026-06-26 21:29:15 +08:00
committed by GitHub
parent 8e036a2f38
commit 4a7c931eca
11 changed files with 248 additions and 110 deletions
@@ -76,15 +76,15 @@ test('checker reports missing legacy projection and stale state', async t => {
const user = await t.context.models.user.create({
email: `${randomUUID()}@affine.pro`,
});
await t.context.entitlement.upsertFromCloudSubscription({
targetId: user.id,
plan: 'pro',
recurring: SubscriptionRecurring.Monthly,
status: 'active',
});
await t.context.db.subscription.delete({
where: { targetId_plan: { targetId: user.id, plan: 'pro' } },
});
await t.context.entitlement.upsertFromCloudSubscription(
{
targetId: user.id,
plan: 'pro',
recurring: SubscriptionRecurring.Monthly,
status: 'active',
},
{ emit: false }
);
await t.context.db.effectiveUserQuotaState.update({
where: { userId: user.id },
data: {
@@ -48,18 +48,24 @@ test('projects user entitlement to legacy user features and subscriptions', asyn
email: `${randomUUID()}@affine.pro`,
});
await t.context.entitlement.upsertFromCloudSubscription({
targetId: user.id,
plan: SubscriptionPlan.Pro,
recurring: SubscriptionRecurring.Yearly,
status: 'active',
});
await t.context.entitlement.upsertFromCloudSubscription({
targetId: user.id,
plan: SubscriptionPlan.AI,
recurring: SubscriptionRecurring.Monthly,
status: 'active',
});
await t.context.entitlement.upsertFromCloudSubscription(
{
targetId: user.id,
plan: SubscriptionPlan.Pro,
recurring: SubscriptionRecurring.Yearly,
status: 'active',
},
{ emit: false }
);
await t.context.entitlement.upsertFromCloudSubscription(
{
targetId: user.id,
plan: SubscriptionPlan.AI,
recurring: SubscriptionRecurring.Monthly,
status: 'active',
},
{ emit: false }
);
await t.context.projection.onEntitlementChanged({
targetType: 'user',
targetId: user.id,