feat(desktop): empty-state for friends list

This commit is contained in:
byGalax
2026-05-16 16:54:12 +02:00
parent b7d7a85253
commit 88409aff5d
+23 -1
View File
@@ -8,12 +8,14 @@ import {
sendFriendRequest, sendFriendRequest,
} from '@chat-app/shared/friends'; } from '@chat-app/shared/friends';
import { extractErrorCode } from '@chat-app/shared/i18n'; import { extractErrorCode } from '@chat-app/shared/i18n';
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { Avatar } from '../components/Avatar'; import { Avatar } from '../components/Avatar';
import { EmptyState } from '../components/EmptyState';
import { import {
AddUserIcon,
AlertIcon, AlertIcon,
ChatBubbleIcon, ChatBubbleIcon,
CheckCircleIcon, CheckCircleIcon,
@@ -39,6 +41,11 @@ export function FriendsPage() {
const [searchError, setSearchError] = useState<string | null>(null); const [searchError, setSearchError] = useState<string | null>(null);
const [pendingId, setPendingId] = useState<string | null>(null); const [pendingId, setPendingId] = useState<string | null>(null);
const [actionError, setActionError] = useState<string | null>(null); const [actionError, setActionError] = useState<string | null>(null);
const searchInputRef = useRef<HTMLInputElement | null>(null);
const focusSearch = useCallback(() => {
searchInputRef.current?.focus();
}, []);
useEffect(() => { useEffect(() => {
const id = window.setTimeout(() => setDebounced(query.trim()), 250); const id = window.setTimeout(() => setDebounced(query.trim()), 250);
@@ -119,6 +126,7 @@ export function FriendsPage() {
<div className="relative"> <div className="relative">
<SearchIcon className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-fg-muted" /> <SearchIcon className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-fg-muted" />
<input <input
ref={searchInputRef}
type="search" type="search"
value={query} value={query}
onChange={(e) => setQuery(e.target.value)} onChange={(e) => setQuery(e.target.value)}
@@ -160,6 +168,19 @@ export function FriendsPage() {
{loading ? ( {loading ? (
<LoadingRow /> <LoadingRow />
) : tab === 'friends' ? ( ) : tab === 'friends' ? (
accepted.length === 0 ? (
<EmptyState
icon={<AddUserIcon className="h-8 w-8" />}
title={t('app:friends.empty_title', { defaultValue: 'Noch keine Freunde' })}
description={t('app:friends.empty_desc', {
defaultValue: 'Suche einen Friend per Username oder schicke eine Einladung.',
})}
action={{
label: t('app:friends.empty_cta', { defaultValue: 'Friend hinzufügen' }),
onClick: focusSearch,
}}
/>
) : (
<FriendList <FriendList
items={accepted} items={accepted}
emptyKey="app:friends.empty_friends" emptyKey="app:friends.empty_friends"
@@ -178,6 +199,7 @@ export function FriendsPage() {
/> />
)} )}
/> />
)
) : tab === 'pending' ? ( ) : tab === 'pending' ? (
<FriendList <FriendList
items={outgoing} items={outgoing}