feat(frontend): add flags to user page
This commit is contained in:
		
							parent
							
								
									f539902711
								
							
						
					
					
						commit
						dc18ab60d2
					
				
					 10 changed files with 68 additions and 5 deletions
				
			
		|  | @ -21,3 +21,9 @@ | ||||||
| @import "@fontsource/firago/400.css"; | @import "@fontsource/firago/400.css"; | ||||||
| @import "@fontsource/firago/400-italic.css"; | @import "@fontsource/firago/400-italic.css"; | ||||||
| @import "@fontsource/firago/700.css"; | @import "@fontsource/firago/700.css"; | ||||||
|  | 
 | ||||||
|  | .pride-flag { | ||||||
|  | 	height: 1.5rem; | ||||||
|  | 	max-width: 200px; | ||||||
|  | 	border-radius: 3px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| import { CustomPreference, FieldEntry, Pronoun } from "~/lib/api/user"; | import { CustomPreference, FieldEntry, Pronoun } from "~/lib/api/user"; | ||||||
| import StatusLine from "~/components/StatusLine"; | import StatusLine from "~/components/profile/StatusLine"; | ||||||
| 
 | 
 | ||||||
| export default function ProfileField({ | export default function ProfileField({ | ||||||
| 	name, | 	name, | ||||||
							
								
								
									
										28
									
								
								Foxnouns.Frontend/app/components/profile/ProfileFlag.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								Foxnouns.Frontend/app/components/profile/ProfileFlag.tsx
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | ||||||
|  | import type { PrideFlag } from "~/lib/api/user"; | ||||||
|  | import { OverlayTrigger, Tooltip } from "react-bootstrap"; | ||||||
|  | 
 | ||||||
|  | export default function ProfileFlag({ flag }: { flag: PrideFlag }) { | ||||||
|  | 	return ( | ||||||
|  | 		<span className="mx-2 my-1"> | ||||||
|  | 			<OverlayTrigger | ||||||
|  | 				key={flag.id} | ||||||
|  | 				placement="top" | ||||||
|  | 				overlay={ | ||||||
|  | 					<Tooltip id={flag.id} aria-hidden={true}> | ||||||
|  | 						{flag.description ?? flag.name} | ||||||
|  | 					</Tooltip> | ||||||
|  | 				} | ||||||
|  | 			> | ||||||
|  | 				<span> | ||||||
|  | 					<img | ||||||
|  | 						className="pride-flag" | ||||||
|  | 						src={flag.image_url} | ||||||
|  | 						alt={flag.description ?? flag.name} | ||||||
|  | 						style={{ pointerEvents: "none" }} | ||||||
|  | 					/> | ||||||
|  | 				</span> | ||||||
|  | 			</OverlayTrigger>{" "} | ||||||
|  | 			{flag.name} | ||||||
|  | 		</span> | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  | @ -7,8 +7,8 @@ import { | ||||||
| 	Pronoun, | 	Pronoun, | ||||||
| } from "~/lib/api/user"; | } from "~/lib/api/user"; | ||||||
| import classNames from "classnames"; | import classNames from "classnames"; | ||||||
| import StatusIcon from "~/components/StatusIcon"; | import StatusIcon from "~/components/profile/StatusIcon"; | ||||||
| import PronounLink from "~/components/PronounLink"; | import PronounLink from "~/components/profile/PronounLink"; | ||||||
| 
 | 
 | ||||||
| export default function StatusLine({ | export default function StatusLine({ | ||||||
| 	entry, | 	entry, | ||||||
							
								
								
									
										5
									
								
								Foxnouns.Frontend/app/lib/api/member.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								Foxnouns.Frontend/app/lib/api/member.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | import { PartialMember, PrideFlag } from "~/lib/api/user"; | ||||||
|  | 
 | ||||||
|  | export type Member = PartialMember & { | ||||||
|  | 	flags: PrideFlag[]; | ||||||
|  | }; | ||||||
|  | @ -13,6 +13,7 @@ export type User = PartialUser & { | ||||||
| 	names: FieldEntry[]; | 	names: FieldEntry[]; | ||||||
| 	pronouns: Pronoun[]; | 	pronouns: Pronoun[]; | ||||||
| 	fields: Field[]; | 	fields: Field[]; | ||||||
|  | 	flags: PrideFlag[]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export type UserWithMembers = User & { members: PartialMember[] }; | export type UserWithMembers = User & { members: PartialMember[] }; | ||||||
|  | @ -50,6 +51,13 @@ export type Field = { | ||||||
| 	entries: FieldEntry[]; | 	entries: FieldEntry[]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | export type PrideFlag = { | ||||||
|  | 	id: string; | ||||||
|  | 	image_url: string; | ||||||
|  | 	name: string; | ||||||
|  | 	description: string | null; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| export type CustomPreference = { | export type CustomPreference = { | ||||||
| 	icon: string; | 	icon: string; | ||||||
| 	tooltip: string; | 	tooltip: string; | ||||||
|  |  | ||||||
|  | @ -6,12 +6,13 @@ import { loader as rootLoader } from "~/root"; | ||||||
| import { Alert, Button, Pagination } from "react-bootstrap"; | import { Alert, Button, Pagination } from "react-bootstrap"; | ||||||
| import { Trans, useTranslation } from "react-i18next"; | import { Trans, useTranslation } from "react-i18next"; | ||||||
| import { renderMarkdown } from "~/lib/markdown"; | import { renderMarkdown } from "~/lib/markdown"; | ||||||
| import ProfileLink from "~/components/ProfileLink"; | import ProfileLink from "~/components/profile/ProfileLink"; | ||||||
| import ProfileField from "~/components/ProfileField"; | import ProfileField from "~/components/profile/ProfileField"; | ||||||
| import { PersonPlusFill } from "react-bootstrap-icons"; | import { PersonPlusFill } from "react-bootstrap-icons"; | ||||||
| import { defaultAvatarUrl } from "~/lib/utils"; | import { defaultAvatarUrl } from "~/lib/utils"; | ||||||
| import MemberCard from "~/routes/$username/MemberCard"; | import MemberCard from "~/routes/$username/MemberCard"; | ||||||
| import { ReactNode } from "react"; | import { ReactNode } from "react"; | ||||||
|  | import ProfileFlag from "~/components/profile/ProfileFlag"; | ||||||
| 
 | 
 | ||||||
| export const meta: MetaFunction<typeof loader> = ({ data }) => { | export const meta: MetaFunction<typeof loader> = ({ data }) => { | ||||||
| 	const { user } = data!; | 	const { user } = data!; | ||||||
|  | @ -92,6 +93,13 @@ export default function UserPage() { | ||||||
| 							height={200} | 							height={200} | ||||||
| 							className="rounded-circle img-fluid" | 							className="rounded-circle img-fluid" | ||||||
| 						/> | 						/> | ||||||
|  | 						{user.flags && user.bio && ( | ||||||
|  | 							<div className="d-flex flex-wrap m-4"> | ||||||
|  | 								{user.flags.map((f, i) => ( | ||||||
|  | 									<ProfileFlag flag={f} key={i} /> | ||||||
|  | 								))} | ||||||
|  | 							</div> | ||||||
|  | 						)} | ||||||
| 					</div> | 					</div> | ||||||
| 					<div className="col-md"> | 					<div className="col-md"> | ||||||
| 						{user.display_name ? ( | 						{user.display_name ? ( | ||||||
|  | @ -146,6 +154,14 @@ export default function UserPage() { | ||||||
| 					))} | 					))} | ||||||
| 				</div> | 				</div> | ||||||
| 			</div> | 			</div> | ||||||
|  | 			{/* If a user or member has no bio, flags are displayed in a row below the other profile info, rather than just below the avatar */} | ||||||
|  | 			{user.flags && !user.bio && ( | ||||||
|  | 				<div className="d-flex flex-wrap m-4"> | ||||||
|  | 					{user.flags.map((f, i) => ( | ||||||
|  | 						<ProfileFlag flag={f} key={i} /> | ||||||
|  | 					))} | ||||||
|  | 				</div> | ||||||
|  | 			)} | ||||||
| 			{(members.length > 0 || isMeUser) && ( | 			{(members.length > 0 || isMeUser) && ( | ||||||
| 				<> | 				<> | ||||||
| 					<hr /> | 					<hr /> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue