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:
@@ -44,12 +44,14 @@ function mockApi({ my = DEFAULT_MY, plans = PLANS }: { my?: any; plans?: any[] }
|
|||||||
beforeEach(() => { get.mockReset(); mockApi(); });
|
beforeEach(() => { get.mockReset(); mockApi(); });
|
||||||
|
|
||||||
describe('SubscriptionPage', () => {
|
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' });
|
renderWithProviders(<SubscriptionPage />, { route: '/admin/subscription' });
|
||||||
expect(await screen.findByText('پلن پایه')).toBeInTheDocument();
|
expect(await screen.findByText('پلن پایه')).toBeInTheDocument();
|
||||||
expect(screen.getByText('پلن رایگان')).toBeInTheDocument();
|
expect(screen.getByText('پلن رایگان')).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 () => {
|
it('shows the current-plan card without an expiry warning when the plan is healthy', async () => {
|
||||||
|
|||||||
@@ -32,8 +32,9 @@ const CARD_FEATURE_LABELS: Record<string, string> = {
|
|||||||
insurance: 'مدیریت بیمه',
|
insurance: 'مدیریت بیمه',
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The plan highlighted as "most popular" in the UI (no backend flag exists). */
|
/** The plan highlighted as "most popular" in the UI (no backend flag exists);
|
||||||
const POPULAR_PLAN_NAME = 'basic';
|
* 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 }> = {
|
const PLAN_META: Record<string, { label: string; desc: string; tint: string }> = {
|
||||||
free: { label: 'رایگان', desc: 'مناسب برای شروع کار', tint: 'var(--surface-2)' },
|
free: { label: 'رایگان', desc: 'مناسب برای شروع کار', tint: 'var(--surface-2)' },
|
||||||
@@ -137,9 +138,9 @@ export default function SubscriptionPage() {
|
|||||||
|
|
||||||
{/* ── Plan cards ── */}
|
{/* ── Plan cards ── */}
|
||||||
{plansLoading ? (
|
{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) => (
|
{[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>
|
</div>
|
||||||
) : plans.length === 0 ? (
|
) : plans.length === 0 ? (
|
||||||
@@ -147,7 +148,7 @@ export default function SubscriptionPage() {
|
|||||||
در حال حاضر پلنی برای نمایش وجود ندارد.
|
در حال حاضر پلنی برای نمایش وجود ندارد.
|
||||||
</div>
|
</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) => (
|
{plans.map((plan) => (
|
||||||
<PlanCard
|
<PlanCard
|
||||||
key={plan.uuid}
|
key={plan.uuid}
|
||||||
@@ -364,7 +365,7 @@ function PlanCard({
|
|||||||
<div
|
<div
|
||||||
data-testid={`plan-card-${plan.name}`}
|
data-testid={`plan-card-${plan.name}`}
|
||||||
style={{
|
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)',
|
border: isSelected ? '2px solid #494cb3' : '2px solid var(--border)',
|
||||||
background: 'var(--surface)', display: 'flex', flexDirection: 'column',
|
background: 'var(--surface)', display: 'flex', flexDirection: 'column',
|
||||||
padding: 16, position: 'relative', overflow: 'hidden',
|
padding: 16, position: 'relative', overflow: 'hidden',
|
||||||
|
|||||||
Reference in New Issue
Block a user