Trying to figure out avatar urls. Not easy.
This commit is contained in:
@ -5,17 +5,28 @@ import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { useAuth, useTVMode } from '@/components/context';
|
||||
import {
|
||||
getRecentUsersWithStatuses,
|
||||
getSignedUrl,
|
||||
updateStatuses,
|
||||
updateUserStatus,
|
||||
type UserWithStatus,
|
||||
} from '@/lib/hooks';
|
||||
import { Drawer, DrawerTrigger, Loading } from '@/components/ui';
|
||||
import {
|
||||
Avatar,
|
||||
AvatarImage,
|
||||
AvatarFallback,
|
||||
BasedAvatarImage,
|
||||
BasedAvatarFallback,
|
||||
Drawer,
|
||||
DrawerTrigger,
|
||||
Loading
|
||||
} from '@/components/ui';
|
||||
import { SubmitButton } from '@/components/default';
|
||||
import { toast } from 'sonner';
|
||||
import { HistoryDrawer } from '@/components/status';
|
||||
import type { Profile } from '@/utils/supabase';
|
||||
import type { RealtimeChannel } from '@supabase/supabase-js';
|
||||
import { makeConditionalClassName } from '@/lib/utils';
|
||||
import { User } from 'lucide-react';
|
||||
|
||||
type TechTableProps = {
|
||||
initialStatuses: UserWithStatus[];
|
||||
@ -47,6 +58,22 @@ export const TechTable = ({
|
||||
}
|
||||
}, []);
|
||||
|
||||
const fetchAvatarUrl = useCallback(async (url: string) => {
|
||||
try {
|
||||
const avatarResponse = await getSignedUrl({
|
||||
bucket: 'avatars',
|
||||
url,
|
||||
transform: { width: 128, height: 128 },
|
||||
});
|
||||
if (!avatarResponse.success) {
|
||||
throw new Error(avatarResponse.error);
|
||||
}
|
||||
return avatarResponse.data;
|
||||
} catch (error) {
|
||||
console.error('Error fetching avatar URL:', error);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Initial load
|
||||
useEffect(() => {
|
||||
const loadData = async () => {
|
||||
@ -225,7 +252,7 @@ export const TechTable = ({
|
||||
/>
|
||||
</th>
|
||||
)}
|
||||
<th className={thClassName}>Name</th>
|
||||
<th className={thClassName}>Technician</th>
|
||||
<th className={thClassName}>
|
||||
<Drawer>
|
||||
<DrawerTrigger
|
||||
@ -261,7 +288,25 @@ export const TechTable = ({
|
||||
</td>
|
||||
)}
|
||||
<td className={tdClassName}>
|
||||
{userWithStatus.user.full_name ?? 'Unknown User'}
|
||||
<div className='flex'>
|
||||
<Avatar>
|
||||
{userWithStatus.user.avatar_url ? (
|
||||
<BasedAvatarImage
|
||||
src={userWithStatus.avatar_url}
|
||||
fullName={userWithStatus.user.full_name ?? ''}
|
||||
width={64}
|
||||
height={64}
|
||||
/>
|
||||
): (
|
||||
<BasedAvatarFallback
|
||||
className='text-md'
|
||||
fullName={userWithStatus.user.full_name}
|
||||
/>
|
||||
)}
|
||||
</Avatar>
|
||||
<p>{userWithStatus.user.full_name ?? 'Unknown User'}</p>
|
||||
<p>{userWithStatus.avatar_url}</p>
|
||||
</div>
|
||||
</td>
|
||||
<td className={tdClassName}>
|
||||
<Drawer>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
import * as React from 'react';
|
||||
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
||||
import { User } from 'lucide-react';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
@ -21,6 +22,25 @@ function Avatar({
|
||||
);
|
||||
}
|
||||
|
||||
type BasedAvatarImageProps = React.ComponentProps<typeof AvatarPrimitive.Image> & {
|
||||
fullName: string;
|
||||
};
|
||||
|
||||
function BasedAvatarImage({
|
||||
fullName,
|
||||
className,
|
||||
...props
|
||||
}: BasedAvatarImageProps) {
|
||||
return (
|
||||
<AvatarPrimitive.Image
|
||||
data-slot='avatar-image'
|
||||
className={cn('aspect-square size-full', className)}
|
||||
alt={fullName.split(' ').map((n) => n[0]).join('').toUpperCase()}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function AvatarImage({
|
||||
className,
|
||||
...props
|
||||
@ -34,10 +54,42 @@ function AvatarImage({
|
||||
);
|
||||
}
|
||||
|
||||
type BasedAvatarFallbackProps =
|
||||
React.ComponentProps<typeof AvatarPrimitive.Fallback> & {
|
||||
fullName?: string | null;
|
||||
};
|
||||
|
||||
function BasedAvatarFallback({
|
||||
fullName = null,
|
||||
className,
|
||||
...props
|
||||
}: BasedAvatarFallbackProps) {
|
||||
return (
|
||||
<AvatarPrimitive.Fallback
|
||||
data-slot='avatar-fallback'
|
||||
className={cn(
|
||||
'bg-muted flex size-full items-center justify-center rounded-full',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{fullName ? (
|
||||
fullName
|
||||
.split(' ')
|
||||
.map((n) => n[0])
|
||||
.join('')
|
||||
.toUpperCase()
|
||||
) : (
|
||||
<User size={64} />
|
||||
)}
|
||||
</AvatarPrimitive.Fallback>
|
||||
);
|
||||
}
|
||||
|
||||
function AvatarFallback({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
|
||||
}: React.ComponentProps<typeof AvatarPrimitive.Fallback & {fullName: string}>) {
|
||||
return (
|
||||
<AvatarPrimitive.Fallback
|
||||
data-slot='avatar-fallback'
|
||||
@ -50,4 +102,4 @@ function AvatarFallback({
|
||||
);
|
||||
}
|
||||
|
||||
export { Avatar, AvatarImage, AvatarFallback };
|
||||
export { Avatar, AvatarImage, BasedAvatarImage, AvatarFallback, BasedAvatarFallback };
|
||||
|
@ -1,12 +1,13 @@
|
||||
'use client';
|
||||
import { createClient } from '@/utils/supabase';
|
||||
import type { Profile, Result } from '@/utils/supabase';
|
||||
import { getUser, getProfile } from '@/lib/hooks';
|
||||
import { getUser, getProfile, getSignedUrl } from '@/lib/hooks';
|
||||
|
||||
export type UserWithStatus = {
|
||||
id?: string;
|
||||
user: Profile;
|
||||
status: string;
|
||||
avatar_url?: string;
|
||||
created_at: string;
|
||||
updated_by?: Profile;
|
||||
};
|
||||
@ -53,7 +54,21 @@ export const getRecentUsersWithStatuses = async (): Promise<
|
||||
return true;
|
||||
});
|
||||
|
||||
return { success: true, data: filtered };
|
||||
const filteredWithAvatars: UserWithStatus[] = filtered;
|
||||
|
||||
for (let userWithStatus of filteredWithAvatars) {
|
||||
if (!userWithStatus.user.avatar_url) continue;
|
||||
const avatarResponse = await getSignedUrl({
|
||||
bucket: 'avatars',
|
||||
url: userWithStatus.user.avatar_url,
|
||||
transform: { width: 128, height: 128 },
|
||||
});
|
||||
if (!avatarResponse.success) continue;
|
||||
else userWithStatus = { ...userWithStatus, avatar_url: avatarResponse.data };
|
||||
}
|
||||
console.log('filteredWithAvatars', filteredWithAvatars);
|
||||
|
||||
return { success: true, data: filteredWithAvatars };
|
||||
} catch (error) {
|
||||
return { success: false, error: `Error: ${error as Error}` };
|
||||
}
|
||||
|
Reference in New Issue
Block a user