feat(frontend): support multiple avatar urls

This commit is contained in:
Sam 2022-09-20 14:12:46 +02:00
parent 85a061ebc5
commit f2a298da75
4 changed files with 65 additions and 10 deletions

View File

@ -0,0 +1,31 @@
import { HTMLAttributes } from "react";
export interface Props extends HTMLAttributes<Props> {
urls: string[];
alt: string;
}
export default function FallbackImage({ urls, alt, className }: Props) {
const fallbackUrl = urls.pop()!;
urls.push(fallbackUrl);
return (
<picture className={className}>
{urls.length !== 0 &&
urls.map((url, key) => {
let contentType: string;
if (url.endsWith(".webp")) {
contentType = "image/webp";
} else if (url.endsWith(".jpg") || url.endsWith(".jpeg")) {
contentType = "image/jpeg";
} else if (url.endsWith(".png")) {
contentType = "image/png";
} else {
contentType = "application/octet-stream";
}
return <source key={key} srcSet={url} type={contentType} />;
})}
<img src={fallbackUrl} alt={alt} className={className} />
</picture>
);
}

View File

@ -39,22 +39,22 @@ export default function FieldCard({
<HeartFill className="inline" /> {linkPronoun(entry)} <HeartFill className="inline" /> {linkPronoun(entry)}
</p> </p>
))} ))}
{field.okay?.length !== 0 && ( {field.okay && field.okay.length !== 0 && (
<p> <p>
<HandThumbsUp className="inline" /> {field.okay!.join(", ")} <HandThumbsUp className="inline" /> {field.okay!.join(", ")}
</p> </p>
)} )}
{field.jokingly?.length !== 0 && ( {field.jokingly && field.jokingly.length !== 0 && (
<p> <p>
<EmojiLaughing className="inline" /> {field.jokingly!.join(", ")} <EmojiLaughing className="inline" /> {field.jokingly!.join(", ")}
</p> </p>
)} )}
{field.friends_only?.length !== 0 && ( {field.friends_only && field.friends_only.length !== 0 && (
<p> <p>
<People className="inline" /> {field.friends_only!.join(", ")} <People className="inline" /> {field.friends_only!.join(", ")}
</p> </p>
)} )}
{field.avoid?.length !== 0 && ( {field.avoid && field.avoid.length !== 0 && (
<p className="text-slate-600 dark:text-slate-400"> <p className="text-slate-600 dark:text-slate-400">
<HandThumbsDown className="inline" /> {field.avoid!.join(", ")} <HandThumbsDown className="inline" /> {field.avoid!.join(", ")}
</p> </p>

View File

@ -1,5 +1,4 @@
export interface MeUser extends User { export interface MeUser extends User {
avatar_source: string | null;
discord: string | null; discord: string | null;
discord_username: string | null; discord_username: string | null;
} }
@ -9,7 +8,7 @@ export interface User {
username: string; username: string;
display_name: string | null; display_name: string | null;
bio: string | null; bio: string | null;
avatar_url: string | null; avatar_urls: string[] | null;
links: string[] | null; links: string[] | null;
members: PartialMember[]; members: PartialMember[];
fields: Field[]; fields: Field[];
@ -21,6 +20,17 @@ export interface PartialMember {
avatar_url: string | null; avatar_url: string | null;
} }
export interface Name {
name: string;
status: WordStatus;
}
export interface Pronoun {
display_text?: string;
pronouns: string;
status: WordStatus;
}
export interface Field { export interface Field {
name: string; name: string;
favourite: string[] | null; favourite: string[] | null;
@ -36,6 +46,14 @@ export interface APIError {
details?: string; details?: string;
} }
export enum WordStatus {
Favourite = 1,
Okay = 2,
Jokingly = 3,
FriendsOnly = 4,
Avoid = 5,
}
export enum ErrorCode { export enum ErrorCode {
BadRequest = 400, BadRequest = 400,
Forbidden = 403, Forbidden = 403,

View File

@ -9,6 +9,7 @@ import Image from "next/image";
import { userState } from "../../../lib/state"; import { userState } from "../../../lib/state";
import { useRecoilValue } from "recoil"; import { useRecoilValue } from "recoil";
import Link from "next/link"; import Link from "next/link";
import FallbackImage from "../../../components/FallbackImage";
interface Props { interface Props {
user: User; user: User;
@ -39,13 +40,18 @@ export default function Index({ user }: Props) {
)} )}
<div className="container mx-auto"> <div className="container mx-auto">
<div className="flex flex-col m-2 p-2 lg:flex-row justify-center lg:justify-start items-center space-y-4 lg:space-y-0 lg:space-x-16 lg:items-start border-b border-slate-200 dark:border-slate-700"> <div className="flex flex-col m-2 p-2 lg:flex-row justify-center lg:justify-start items-center space-y-4 lg:space-y-0 lg:space-x-16 lg:items-start border-b border-slate-200 dark:border-slate-700">
{user.avatar_url && ( {user.avatar_urls && user.avatar_urls.length !== 0 && (
// eslint-disable-next-line @next/next/no-img-element <FallbackImage
<img
className="max-w-xs rounded-full" className="max-w-xs rounded-full"
src={user.avatar_url} urls={user.avatar_urls}
alt={`@${user.username}'s avatar`} alt={`@${user.username}'s avatar`}
/> />
// eslint-disable-next-line @next/next/no-img-element
// <img
// className="max-w-xs rounded-full"
// src={user.avatar_url}
// alt={`@${user.username}'s avatar`}
// />
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
{user.display_name && ( {user.display_name && (