Files
polskalokalnie/frontend/src/Avatar.tsx
T

46 lines
1.7 KiB
TypeScript

/**
* Zdjecie profilowe uzytkownika - jedno miejsce dla calej aplikacji.
*
* Uzytkownik ustawia zdjecie raz w /konto/ustawienia, a backend dokleja je do profilu
* (/api/auth/me, profil publiczny, karta sprzedajacego przy ogloszeniu). Gdy zdjecia nie ma,
* rysujemy inicjaly na zielonym tle - ten sam wyglad co awatar w prawym gornym rogu naglowka.
*
* Rozmiar i pozycje nadaje klasa z miejsca uzycia (np. .account-trigger-avatar), a wspolna
* klasa .avatar odpowiada za ksztalt, kolor tla i wpasowanie zdjecia w kolo.
*/
type AvatarProps = {
/** Nazwa uzytkownika - zrodlo inicjalow i tekstu alternatywnego zdjecia. */
name: string;
/** Zdjecie jako data URL. Puste albo null oznacza, ze uzytkownik zadnego nie ustawil. */
image?: string | null;
/** Klasa miejsca uzycia, ktora nadaje rozmiar. */
className?: string;
/** Sama pierwsza litera imienia zamiast dwoch inicjalow - tak wyglada karta sprzedajacego. */
singleLetter?: boolean;
};
/** Inicjaly z nazwy: "Jan Kowalski" -> "JK", "joanna" -> "JO", pusta nazwa -> "??". */
export function initialsFrom(name: string): string {
const parts = name.trim().split(/\s+/).filter(Boolean);
if (parts.length === 0) {
return '??';
}
if (parts.length === 1) {
return parts[0].slice(0, 2).toUpperCase();
}
return `${parts[0][0]}${parts[1][0]}`.toUpperCase();
}
export function Avatar({ name, image, className, singleLetter }: AvatarProps) {
const trimmed = image?.trim();
const letters = singleLetter ? (name.trim()[0] ?? '?').toUpperCase() : initialsFrom(name);
return (
<span className={className ? `avatar ${className}` : 'avatar'}>
{trimmed
? <img src={trimmed} alt={`Zdjęcie profilowe: ${name}`} />
: letters}
</span>
);
}