fix(subscription): plan cards fill row, popular = professional

- Replace wrapping flex (maxWidth cap) with a fills-the-row grid
  (repeat(auto-fit, minmax(230px, 1fr))) so the three cards sit in one row
  and grow to the content width — removes the empty gap and stray wrap
- Move the most-popular highlight to the professional (top) plan, matching
  clinic-pro-tauri

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
hamed
2026-07-14 14:49:58 +03:30
co-authored by Claude Opus 4.8
parent 37fc56dc75
commit 1c1cdfab07
2 changed files with 11 additions and 8 deletions
+4 -2
View File
@@ -44,12 +44,14 @@ function mockApi({ my = DEFAULT_MY, plans = PLANS }: { my?: any; plans?: any[] }
beforeEach(() => { get.mockReset(); mockApi(); });
describe('SubscriptionPage', () => {
it('renders the three plans with the most-popular badge on the basic plan', async () => {
it('renders the three plans with the most-popular badge on the professional plan', async () => {
renderWithProviders(<SubscriptionPage />, { route: '/admin/subscription' });
expect(await screen.findByText('پلن پایه')).toBeInTheDocument();
expect(screen.getByText('پلن رایگان')).toBeInTheDocument();
expect(screen.getByText('پلن حرفه‌ای')).toBeInTheDocument();
expect(screen.getByText('محبوب‌ترین')).toBeInTheDocument();
// most-popular badge sits on the professional (top) card, matching tauri
const proCard = within(screen.getByTestId('plan-card-professional'));
expect(proCard.getByText('محبوب‌ترین')).toBeInTheDocument();
});
it('shows the current-plan card without an expiry warning when the plan is healthy', async () => {
+7 -6
View File
@@ -32,8 +32,9 @@ const CARD_FEATURE_LABELS: Record<string, string> = {
insurance: 'مدیریت بیمه',
};
/** The plan highlighted as "most popular" in the UI (no backend flag exists). */
const POPULAR_PLAN_NAME = 'basic';
/** The plan highlighted as "most popular" in the UI (no backend flag exists);
* matches clinic-pro-tauri, which flags the professional (top) plan. */
const POPULAR_PLAN_NAME = 'professional';
const PLAN_META: Record<string, { label: string; desc: string; tint: string }> = {
free: { label: 'رایگان', desc: 'مناسب برای شروع کار', tint: 'var(--surface-2)' },
@@ -137,9 +138,9 @@ export default function SubscriptionPage() {
{/* ── Plan cards ── */}
{plansLoading ? (
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 16, justifyContent: 'flex-end', width: '100%' }}>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(230px, 1fr))', gap: 16, width: '100%' }}>
{[1, 2, 3].map((i) => (
<div key={i} className="skeleton" style={{ flex: '1 1 280px', minWidth: 250, maxWidth: 340, height: 522, borderRadius: 10 }} />
<div key={i} className="skeleton" style={{ height: 522, borderRadius: 10 }} />
))}
</div>
) : plans.length === 0 ? (
@@ -147,7 +148,7 @@ export default function SubscriptionPage() {
در حال حاضر پلنی برای نمایش وجود ندارد.
</div>
) : (
<div style={{ display: 'flex', flexDirection: 'row', flexWrap: 'wrap', gap: 16, justifyContent: 'flex-end', width: '100%' }}>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(230px, 1fr))', gap: 16, width: '100%' }}>
{plans.map((plan) => (
<PlanCard
key={plan.uuid}
@@ -364,7 +365,7 @@ function PlanCard({
<div
data-testid={`plan-card-${plan.name}`}
style={{
flex: '1 1 280px', minWidth: 250, maxWidth: 340, height: 522, borderRadius: 10,
width: '100%', minWidth: 0, height: 522, borderRadius: 10,
border: isSelected ? '2px solid #494cb3' : '2px solid var(--border)',
background: 'var(--surface)', display: 'flex', flexDirection: 'column',
padding: 16, position: 'relative', overflow: 'hidden',