Skip to content

Commit 4a631a3

Browse files
simonhampclaude
andauthored
Simplify customer license UI for expired licenses (#393)
Hide status/expiry noise from the customer license dashboard: - Drop the "License Expired" banner and the "keys cannot be created for expired licenses" notice (suspended messaging is retained). - Hide the sub-key limit (e.g. x/9) once a license is expired. - Remove the Status column and Expires detail from the licenses index and individual license screens. - Remove the "Create Key" button while leaving the creation flow intact. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 9b5761a commit 4a631a3

6 files changed

Lines changed: 43 additions & 116 deletions

File tree

app/Models/License.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ protected function remainingSubLicenses(): Attribute
100100
});
101101
}
102102

103+
public function isExpired(): bool
104+
{
105+
return $this->expires_at && $this->expires_at->isPast();
106+
}
107+
103108
public function canCreateSubLicense(): bool
104109
{
105110
if (! $this->supportsSubLicenses()) {

resources/views/livewire/customer/licenses.blade.php

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,10 @@
99
<flux:table.columns>
1010
<flux:table.column>License</flux:table.column>
1111
<flux:table.column>Key</flux:table.column>
12-
<flux:table.column>Status</flux:table.column>
13-
<flux:table.column>Expires</flux:table.column>
1412
</flux:table.columns>
1513

1614
<flux:table.rows>
1715
@foreach($this->licenses as $license)
18-
@php
19-
$isLegacyLicense = $license->isLegacy();
20-
$daysUntilExpiry = $license->expires_at ? (int) now()->diffInDays($license->expires_at, false) : null;
21-
$needsRenewal = $isLegacyLicense && $daysUntilExpiry !== null && !$license->expires_at->isPast();
22-
23-
$status = match(true) {
24-
$license->is_suspended => 'Suspended',
25-
$license->expires_at && $license->expires_at->isPast() => 'Expired',
26-
$needsRenewal => 'Needs Renewal',
27-
default => 'Active',
28-
};
29-
@endphp
3016
<flux:table.row :key="$license->id">
3117
<flux:table.cell>
3218
<div>
@@ -42,32 +28,6 @@
4228
<flux:table.cell>
4329
<x-customer.masked-key :key-value="$license->key" />
4430
</flux:table.cell>
45-
46-
<flux:table.cell>
47-
<x-customer.status-badge :status="$status" />
48-
</flux:table.cell>
49-
50-
<flux:table.cell>
51-
@if($needsRenewal)
52-
<div>
53-
<span class="font-medium text-blue-600 dark:text-blue-400">
54-
{{ $daysUntilExpiry }} day{{ $daysUntilExpiry === 1 ? '' : 's' }}
55-
</span>
56-
@if($isLegacyLicense)
57-
<flux:text class="text-xs text-blue-500 dark:text-blue-300">Lock in Early Access Pricing</flux:text>
58-
@endif
59-
</div>
60-
@elseif($license->expires_at)
61-
<div>
62-
{{ $license->expires_at->format('M j, Y') }}
63-
@if($license->expires_at->isPast())
64-
<flux:text class="text-xs">Expired {{ $license->expires_at->diffForHumans() }}</flux:text>
65-
@endif
66-
</div>
67-
@else
68-
No expiration
69-
@endif
70-
</flux:table.cell>
7131
</flux:table.row>
7232
@endforeach
7333
</flux:table.rows>
@@ -82,19 +42,10 @@
8242
<flux:table.columns>
8343
<flux:table.column>License</flux:table.column>
8444
<flux:table.column>Key</flux:table.column>
85-
<flux:table.column>Status</flux:table.column>
86-
<flux:table.column>Expires</flux:table.column>
8745
</flux:table.columns>
8846

8947
<flux:table.rows>
9048
@foreach($this->assignedSubLicenses as $subLicense)
91-
@php
92-
$subStatus = match(true) {
93-
$subLicense->is_suspended => 'Suspended',
94-
$subLicense->expires_at && $subLicense->expires_at->isPast() => 'Expired',
95-
default => 'Active',
96-
};
97-
@endphp
9849
<flux:table.row :key="$subLicense->id">
9950
<flux:table.cell>
10051
<div>
@@ -106,23 +57,6 @@
10657
<flux:table.cell>
10758
<x-customer.masked-key :key-value="$subLicense->key" />
10859
</flux:table.cell>
109-
110-
<flux:table.cell>
111-
<x-customer.status-badge :status="$subStatus" />
112-
</flux:table.cell>
113-
114-
<flux:table.cell>
115-
@if($subLicense->expires_at)
116-
<div>
117-
{{ $subLicense->expires_at->format('M j, Y') }}
118-
@if($subLicense->expires_at->isPast())
119-
<flux:text class="text-xs">Expired {{ $subLicense->expires_at->diffForHumans() }}</flux:text>
120-
@endif
121-
</div>
122-
@else
123-
No expiration
124-
@endif
125-
</flux:table.cell>
12660
</flux:table.row>
12761
@endforeach
12862
</flux:table.rows>

resources/views/livewire/customer/licenses/show.blade.php

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,9 @@
2424

2525
{{-- License Information Card --}}
2626
<flux:card class="mb-6">
27-
<div class="flex items-center justify-between mb-4">
28-
<div>
29-
<flux:heading size="lg">License Information</flux:heading>
30-
<flux:text>Details about your NativePHP license.</flux:text>
31-
</div>
32-
<x-customer.status-badge :status="$license->is_suspended ? 'Suspended' : ($license->expires_at && $license->expires_at->isPast() ? 'Expired' : 'Active')" />
27+
<div class="mb-4">
28+
<flux:heading size="lg">License Information</flux:heading>
29+
<flux:text>Details about your NativePHP license.</flux:text>
3330
</div>
3431

3532
<flux:separator />
@@ -80,23 +77,6 @@
8077
<flux:text class="inline text-xs">({{ $license->created_at->diffForHumans() }})</flux:text>
8178
</flux:table.cell>
8279
</flux:table.row>
83-
84-
{{-- Expires --}}
85-
<flux:table.row>
86-
<flux:table.cell class="font-medium text-zinc-500 dark:text-zinc-400">Expires</flux:table.cell>
87-
<flux:table.cell>
88-
@if($license->expires_at)
89-
{{ $license->expires_at->format('F j, Y \a\t g:i A') }}
90-
@if($license->expires_at->isPast())
91-
<flux:text class="inline text-xs">(Expired {{ $license->expires_at->diffForHumans() }})</flux:text>
92-
@else
93-
<flux:text class="inline text-xs">({{ $license->expires_at->diffForHumans() }})</flux:text>
94-
@endif
95-
@else
96-
Never
97-
@endif
98-
</flux:table.cell>
99-
</flux:table.row>
10080
</flux:table.rows>
10181
</flux:table>
10282
</flux:card>
@@ -126,20 +106,11 @@
126106
</flux:callout>
127107
@endif
128108

129-
@if($license->is_suspended || ($license->expires_at && $license->expires_at->isPast()))
109+
@if($license->is_suspended)
130110
<flux:callout variant="warning" icon="exclamation-triangle" class="mt-6">
131-
<flux:callout.heading>
132-
{{ $license->is_suspended ? 'License Suspended' : 'License Expired' }}
133-
</flux:callout.heading>
111+
<flux:callout.heading>License Suspended</flux:callout.heading>
134112
<flux:callout.text>
135-
@if($license->is_suspended)
136-
This license has been suspended. Please contact support for assistance.
137-
@elseif($isLegacyLicense)
138-
This license has expired. You can still renew it to restore access.
139-
<a href="{{ route('license.renewal', $license->key) }}" class="font-medium underline hover:no-underline">Renew now</a>
140-
@else
141-
This license has expired. Please renew your subscription to continue using NativePHP.
142-
@endif
113+
This license has been suspended. Please contact support for assistance.
143114
</flux:callout.text>
144115
</flux:callout>
145116
@endif

resources/views/livewire/sub-license-manager.blade.php

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,11 @@
55
<flux:heading size="lg">
66
Keys
77
<span class="ml-2 text-sm text-zinc-500 dark:text-zinc-400">
8-
({{ $activeSubLicenses->count() }}{{ $license->subLicenseLimit ? '/' . $license->subLicenseLimit : '' }})
8+
({{ $activeSubLicenses->count() }}{{ $license->subLicenseLimit && ! $license->isExpired() ? '/' . $license->subLicenseLimit : '' }})
99
</span>
1010
</flux:heading>
1111
<flux:text>Manage license keys for team members or additional devices.</flux:text>
1212
</div>
13-
@if($license->canCreateSubLicense())
14-
<flux:button variant="primary" wire:click="openCreateModal">
15-
Create Key
16-
</flux:button>
17-
@endif
1813
</div>
1914

2015
@if($license->subLicenses->isEmpty())
@@ -120,15 +115,13 @@
120115
@endif
121116
@endif
122117

123-
@if(!$license->canCreateSubLicense())
118+
@if(!$license->canCreateSubLicense() && ! $license->isExpired())
124119
<flux:callout variant="warning" icon="exclamation-triangle" class="mt-4">
125120
<flux:callout.text>
126121
@if($license->remainingSubLicenses === 0)
127122
You have reached the maximum number of keys for this plan.
128123
@elseif($license->is_suspended)
129124
Keys cannot be created for suspended licenses.
130-
@elseif($license->expires_at && $license->expires_at->isPast())
131-
Keys cannot be created for expired licenses.
132125
@else
133126
Keys cannot be created at this time.
134127
@endif

tests/Feature/CustomerLicenseManagementTest.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ public function test_customer_can_view_individual_license_details(): void
106106
$response->assertSee('pro');
107107
$response->assertSee('test-license-key-123');
108108
$response->assertSee('License Information');
109-
$response->assertSee('Active');
109+
$response->assertDontSee('Active');
110+
$response->assertDontSee('Expires');
110111
}
111112

112113
public function test_customer_cannot_view_other_customers_license_details(): void
@@ -124,36 +125,43 @@ public function test_customer_cannot_view_other_customers_license_details(): voi
124125
$response->assertStatus(404);
125126
}
126127

127-
public function test_license_status_displays_correctly(): void
128+
public function test_license_index_does_not_display_status_or_expiry(): void
128129
{
129130
$user = User::factory()->create();
130131

131132
// Active license
132133
$activeLicense = License::factory()->create([
133134
'user_id' => $user->id,
135+
'key' => 'license-key-one',
134136
'expires_at' => now()->addDays(30),
135137
'is_suspended' => false,
136138
]);
137139

138140
// Expired license
139141
$expiredLicense = License::factory()->create([
140142
'user_id' => $user->id,
143+
'key' => 'license-key-two',
141144
'expires_at' => now()->subDays(1),
142145
'is_suspended' => false,
143146
]);
144147

145148
// Suspended license
146149
$suspendedLicense = License::factory()->create([
147150
'user_id' => $user->id,
151+
'key' => 'license-key-three',
148152
'is_suspended' => true,
149153
]);
150154

151155
$response = $this->actingAs($user)->get('/dashboard/licenses');
152156

153157
$response->assertStatus(200);
154-
$response->assertSee('Active');
155-
$response->assertSee('Expired');
156-
$response->assertSee('Suspended');
158+
$response->assertSee('license-key-one');
159+
$response->assertSee('license-key-two');
160+
$response->assertSee('license-key-three');
161+
$response->assertDontSee('Status');
162+
$response->assertDontSee('Expires');
163+
$response->assertDontSee('Expired');
164+
$response->assertDontSee('Suspended');
157165
}
158166

159167
public function test_customer_can_update_license_name(): void

tests/Feature/CustomerSubLicenseManagementTest.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,6 @@ public function test_license_show_page_displays_sub_licenses(): void
335335
$response->assertSee('Testing Team');
336336
$response->assertSee($subLicense1->key);
337337
$response->assertSee($subLicense2->key);
338-
$response->assertSee('Active');
339338
$response->assertSee('Suspended');
340339
}
341340

@@ -520,4 +519,21 @@ public function test_livewire_component_displays_sublicenses(): void
520519
->assertSee($activeSubLicense->key)
521520
->assertSee($suspendedSubLicense->key);
522521
}
522+
523+
public function test_expired_license_hides_key_limit_and_expired_banner(): void
524+
{
525+
$user = User::factory()->create();
526+
$license = License::factory()->create([
527+
'user_id' => $user->id,
528+
'policy_name' => 'pro', // Pro has a sub-license limit of 9
529+
'is_suspended' => false,
530+
'expires_at' => now()->subDay(),
531+
]);
532+
533+
$this->actingAs($user);
534+
535+
Livewire::test(SubLicenseManager::class, ['license' => $license])
536+
->assertDontSee('/9')
537+
->assertDontSee('Keys cannot be created for expired licenses.');
538+
}
523539
}

0 commit comments

Comments
 (0)