mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-10-31 18:19:43 +00:00
fix(admin): use feature interest composite key
This commit is contained in:
1 parent
a6233d0175
commit
53a48ab6d5
3 files changed
+14
-7
No files matched your search
@@ -1,16 +1,20 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import { formatFeatureName, toRecentFeatureInterest } from './featureInterests';
|
import { featureInterestKey, formatFeatureName, toRecentFeatureInterest } from './featureInterests';
|
||||||
|
|
||||||
describe('toRecentFeatureInterest', () => {
|
describe('toRecentFeatureInterest', () => {
|
||||||
it('preserves the standalone API feature field for dashboard rendering', () => {
|
it('preserves the standalone API feature field for dashboard rendering', () => {
|
||||||
const interest = toRecentFeatureInterest({
|
const interest = toRecentFeatureInterest({
|
||||||
id: 'interest-1',
|
|
||||||
user_id: 'user-1',
|
user_id: 'user-1',
|
||||||
feature: 'better_chat',
|
feature: 'better_chat',
|
||||||
created_at: '2026-09-05T12:00:00.000Z',
|
created_at: '2026-09-05T12:00:00.000Z',
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(interest.feature).toBe('better_chat');
|
expect(interest).toEqual({
|
||||||
|
user_id: 'user-1',
|
||||||
|
feature: 'better_chat',
|
||||||
|
created_at: '2026-09-05T12:00:00.000Z',
|
||||||
|
});
|
||||||
expect(formatFeatureName(interest.feature)).toBe('Better Chat');
|
expect(formatFeatureName(interest.feature)).toBe('Better Chat');
|
||||||
|
expect(featureInterestKey(interest)).toBe('user-1:better_chat');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
export interface FeatureInterestRow {
|
export interface FeatureInterestRow {
|
||||||
id: string;
|
|
||||||
user_id: string;
|
user_id: string;
|
||||||
feature: string;
|
feature: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
@@ -16,13 +15,16 @@ export interface RecentFeatureInterest extends FeatureInterestRow {
|
|||||||
|
|
||||||
export function toRecentFeatureInterest(row: FeatureInterestRow): RecentFeatureInterest {
|
export function toRecentFeatureInterest(row: FeatureInterestRow): RecentFeatureInterest {
|
||||||
return {
|
return {
|
||||||
id: row.id,
|
|
||||||
user_id: row.user_id,
|
user_id: row.user_id,
|
||||||
feature: row.feature,
|
feature: row.feature,
|
||||||
created_at: row.created_at,
|
created_at: row.created_at,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function featureInterestKey(row: Pick<FeatureInterestRow, 'user_id' | 'feature'>): string {
|
||||||
|
return `${row.user_id}:${row.feature}`;
|
||||||
|
}
|
||||||
|
|
||||||
export function formatFeatureName(feature: string): string {
|
export function formatFeatureName(feature: string): string {
|
||||||
return feature
|
return feature
|
||||||
.split('_')
|
.split('_')
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { useRealtimeSubscription } from '@/hooks/useRealtimeSubscription';
|
|||||||
import { RealtimeStatusIndicator } from '@/components/RealtimeStatusIndicator';
|
import { RealtimeStatusIndicator } from '@/components/RealtimeStatusIndicator';
|
||||||
import {
|
import {
|
||||||
formatFeatureName,
|
formatFeatureName,
|
||||||
|
featureInterestKey,
|
||||||
toRecentFeatureInterest,
|
toRecentFeatureInterest,
|
||||||
type FeatureInterestRow,
|
type FeatureInterestRow,
|
||||||
type RecentFeatureInterest,
|
type RecentFeatureInterest,
|
||||||
@@ -80,7 +81,7 @@ export function DashboardPage() {
|
|||||||
? adminData.from('feature_interests').select('created_at, user_id').gte('created_at', startDate.toISOString()).lte('created_at', endDate.toISOString())
|
? adminData.from('feature_interests').select('created_at, user_id').gte('created_at', startDate.toISOString()).lte('created_at', endDate.toISOString())
|
||||||
: Promise.resolve({ data: [] }),
|
: Promise.resolve({ data: [] }),
|
||||||
canViewUsers
|
canViewUsers
|
||||||
? adminData.from<FeatureInterestRow>('feature_interests').select('id, user_id, feature, created_at').order('created_at', { ascending: false }).limit(10)
|
? adminData.from<FeatureInterestRow>('feature_interests').select('user_id, feature, created_at').order('created_at', { ascending: false }).limit(10)
|
||||||
: Promise.resolve({ data: [] }),
|
: Promise.resolve({ data: [] }),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -566,7 +567,7 @@ export function DashboardPage() {
|
|||||||
.toUpperCase();
|
.toUpperCase();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={item.id} className="flex items-center justify-between gap-4 rounded-xl bg-white/5 p-3">
|
<div key={featureInterestKey(item)} className="flex items-center justify-between gap-4 rounded-xl bg-white/5 p-3">
|
||||||
<div className="flex items-center gap-3 min-w-0">
|
<div className="flex items-center gap-3 min-w-0">
|
||||||
<Avatar className="h-8 w-8">
|
<Avatar className="h-8 w-8">
|
||||||
<AvatarImage src={item.profile?.avatar_url || undefined} />
|
<AvatarImage src={item.profile?.avatar_url || undefined} />
|
||||||
|
|||||||
Reference in new issue
Block a user