MAJOR UPPDATE: "First Ai"
feat: add AI categorization for products and enhance user management - Integrated AI service for category suggestions in receipt import and product management. - Added premium subscription feature for users with corresponding API endpoints. - Implemented admin interface for managing pending product suggestions. - Enhanced user management to include premium status and corresponding UI updates. - Updated database schema to support new fields for premium status and product status.
This commit is contained in:
@@ -7,6 +7,7 @@ interface User {
|
||||
username: string;
|
||||
email: string;
|
||||
role: string;
|
||||
isPremium: boolean;
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
createdAt: string;
|
||||
@@ -109,6 +110,21 @@ export default function AnvandareClient({ users: initial, currentUserId }: Props
|
||||
setCopiedPw(false);
|
||||
}
|
||||
|
||||
async function handlePremiumChange(id: number, isPremium: boolean) {
|
||||
setError('');
|
||||
const res = await fetch(`/api/admin-users/${id}`, {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ isPremium }),
|
||||
});
|
||||
if (res.ok) {
|
||||
setUsers((prev) => prev.map((u) => (u.id === id ? { ...u, isPremium } : u)));
|
||||
} else {
|
||||
const data = await res.json().catch(() => ({}));
|
||||
setError(data.message ?? 'Kunde inte ändra plan');
|
||||
}
|
||||
}
|
||||
|
||||
async function handleEmailSave(id: number) {
|
||||
setError('');
|
||||
const res = await fetch(`/api/admin-users/${id}`, {
|
||||
@@ -241,7 +257,7 @@ export default function AnvandareClient({ users: initial, currentUserId }: Props
|
||||
<table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 14 }}>
|
||||
<thead>
|
||||
<tr style={{ background: '#f1f5f9', textAlign: 'left' }}>
|
||||
{['Användare', 'E-post', 'Roll', 'Åtgärder'].map((h) => (
|
||||
{['Användare', 'E-post', 'Roll', 'Plan', 'Åtgärder'].map((h) => (
|
||||
<th
|
||||
key={h}
|
||||
style={{ padding: '0.6rem 0.8rem', borderBottom: '2px solid #e2e8f0' }}
|
||||
@@ -367,6 +383,26 @@ export default function AnvandareClient({ users: initial, currentUserId }: Props
|
||||
)}
|
||||
</td>
|
||||
|
||||
{/* Plan */}
|
||||
<td style={{ padding: '0.6rem 0.8rem' }}>
|
||||
<select
|
||||
value={user.isPremium ? 'paid' : 'free'}
|
||||
onChange={(e) => handlePremiumChange(user.id, e.target.value === 'paid')}
|
||||
style={{
|
||||
padding: '0.25rem 0.4rem',
|
||||
border: '1px solid #cbd5e1',
|
||||
borderRadius: 4,
|
||||
fontSize: 13,
|
||||
background: user.isPremium ? '#fef9c3' : '#f8fafc',
|
||||
color: user.isPremium ? '#854d0e' : '#334155',
|
||||
fontWeight: user.isPremium ? 600 : 400,
|
||||
}}
|
||||
>
|
||||
<option value="free">Free</option>
|
||||
<option value="paid">Paid ✨</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
{/* Åtgärder */}
|
||||
<td style={{ padding: '0.6rem 0.8rem' }}>
|
||||
{isSelf ? (
|
||||
|
||||
Reference in New Issue
Block a user