profile image and time update

This commit is contained in:
BFlat authored and Brandon Thomas committed 2023-10-18 04:15:11 -04:00
1 parent ba31bf47f9
commit a7bd1d97c2
10 files changed
+135 -28

No files matched your search

+1 -1
View File
@@ -33,7 +33,7 @@
"axios": "^0.21.0",
"bulma": "^0.9.0",
"craco": "^0.0.3",
"date-fns": "^2.22.1",
"date-fns": "2.22.1",
"framer-motion": "^6.5.1",
"howler": "^2.2.0",
"i18next": "^21.6.11",
@@ -2,7 +2,7 @@
.fy-accordion-item {
border: 1px solid rgba($white, 0.12);
border-radius: 5px;
border-radius: 0.5rem;
overflow: hidden;
}
@@ -1,4 +1,10 @@
import React, { useState, useRef, useEffect } from "react";
import React, {
useState,
useRef,
useEffect,
createContext,
useContext,
} from "react";
import "./Accordion.scss";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronDown } from "@fortawesome/pro-solid-svg-icons";
@@ -14,50 +20,62 @@ interface AccordionItemProps {
children: React.ReactNode;
}
interface AccordionContextType {
openItems: string[];
toggleItem: (title: string) => void;
}
const AccordionContext = createContext<AccordionContextType | undefined>(
undefined
);
function AccordionItem({
title,
defaultOpen = false,
children,
}: AccordionItemProps) {
const [isOpen, setIsOpen] = useState(defaultOpen);
const { openItems, toggleItem } = useContext(
AccordionContext
) as AccordionContextType;
const isOpen = openItems.includes(title);
const [contentHeight, setContentHeight] = useState<number | undefined>(
defaultOpen ? undefined : 0
isOpen ? undefined : 0
);
const contentRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (isOpen && contentRef.current) {
setContentHeight(contentRef.current.scrollHeight);
} else {
setContentHeight(0);
if (contentRef.current) {
setContentHeight(isOpen ? contentRef.current.scrollHeight : 0);
}
}, [isOpen]);
const heightProps = useSpring({
height: `${contentHeight}px`,
from: {
height: defaultOpen ? "auto" : "0px",
config: { tension: 300, friction: 25 },
},
height: isOpen ? `${contentHeight}px` : "0px",
config: { tension: 300, friction: 25, clamp: true },
});
const contentOpacityProps = useSpring({
opacity: isOpen ? 1 : 0,
config: { tension: 300, friction: 25 },
config: { tension: 300, friction: 25, clamp: true },
});
const handleClick = () => {
toggleItem(title);
};
return (
<div className="fy-accordion-item">
<div
className={`fy-accordion-header p-3 ${isOpen ? "open" : ""}`}
onClick={() => setIsOpen(!isOpen)}
onClick={handleClick}
>
{title}
<span className={`caret-icon ${isOpen ? "caret-rotated" : ""}`}>
<FontAwesomeIcon icon={faChevronDown} />
</span>
</div>
<animated.div style={heightProps}>
<animated.div style={{ ...heightProps, overflow: "hidden" }}>
<animated.div
ref={contentRef}
style={contentOpacityProps}
@@ -71,7 +89,29 @@ function AccordionItem({
}
function Accordion({ children }: AccordionProps) {
return <div className="d-flex flex-column gap-3">{children}</div>;
const [openItems, setOpenItems] = useState<string[]>([]);
const toggleItem = (title: string) => {
if (openItems.includes(title)) {
setOpenItems(openItems.filter((item) => item !== title));
} else {
setOpenItems([...openItems, title]);
}
};
// Initialize openItems based on defaultOpen props of AccordionItem children
useEffect(() => {
const defaultOpenItems = React.Children.toArray(children)
.filter((child: any) => child.props.defaultOpen)
.map((child: any) => child.props.title);
setOpenItems(defaultOpenItems);
}, [children]);
return (
<AccordionContext.Provider value={{ openItems, toggleItem }}>
<div className="d-flex flex-column gap-3">{children}</div>
</AccordionContext.Provider>
);
}
Accordion.Item = AccordionItem;
@@ -1,11 +1,13 @@
@import "scss/colours.scss";
table {
font-size: 14px;
margin-bottom: 0 !important;
}
td {
padding: 8px 16px !important;
min-width: 124px !important;
}
.no-outer-border {
@@ -0,0 +1 @@
export { default } from "./useTimeAgo";
@@ -0,0 +1,44 @@
import { useEffect, useState } from "react";
function useTimeAgo(timestamp: string) {
const [timeAgo, setTimeAgo] = useState<string>("");
useEffect(() => {
const calculateTimeAgo = () => {
const now = new Date();
const then = new Date(timestamp);
const seconds = Math.floor((now.getTime() - then.getTime()) / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
const months = Math.floor(days / 30);
const years = Math.floor(months / 12);
if (years > 0) {
setTimeAgo(`${years} ${years === 1 ? "year" : "years"} ago`);
} else if (months > 0) {
setTimeAgo(`${months} ${months === 1 ? "month" : "months"} ago`);
} else if (days > 0) {
setTimeAgo(`${days} ${days === 1 ? "day" : "days"} ago`);
} else if (hours > 0) {
setTimeAgo(`${hours} ${hours === 1 ? "hour" : "hours"} ago`);
} else if (minutes > 0) {
setTimeAgo(`${minutes} ${minutes === 1 ? "minute" : "minutes"} ago`);
} else {
setTimeAgo(`${seconds} ${seconds === 1 ? "second" : "seconds"} ago`);
}
};
calculateTimeAgo();
// Update the time difference every minute
const intervalId = setInterval(calculateTimeAgo, 60000);
return () => clearInterval(intervalId);
}, [timestamp]);
return timeAgo;
}
export default useTimeAgo;
@@ -148,7 +148,7 @@ styles with important tags:
}
.container {
max-width: 1080px !important;
max-width: 1200px !important;
}
.container,
@@ -12,6 +12,8 @@ export default interface MediaData {
color_index: number;
};
};
model_used: string;
model_link: string;
creator_set_visibility: string;
created_at: string;
updated_at: string;
@@ -14,6 +14,7 @@ import { faCircleExclamation } from "@fortawesome/pro-solid-svg-icons";
import Accordion from "components/common/Accordion";
import DataTable from "components/common/DataTable";
import { Gravatar } from "@storyteller/components/src/elements/Gravatar";
import useTimeAgo from "hooks/useTimeAgo";
interface MediaPageProps {
sessionWrapper: SessionWrapper;
@@ -35,9 +36,11 @@ let dummyMediaData = {
color_index: 3,
},
},
model_used: "Ash Ketchum",
model_link: "/tts/TM:6g1mfb9b6fb8",
creator_set_visibility: "public",
created_at: "2023-10-12T07:49:53Z",
updated_at: "2023-10-12T07:49:53Z",
created_at: "2023-05-12T07:49:53Z",
updated_at: "2023-05-12T07:49:53Z",
};
export default function MediaPage({ sessionWrapper }: MediaPageProps) {
@@ -46,6 +49,8 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) {
const [isLoading, setIsLoading] = useState<boolean>(true);
const [error, setError] = useState<boolean>(false);
const timeCreated = useTimeAgo(mediaData?.created_at || "");
// Simulate API call
useEffect(() => {
setTimeout(() => {
@@ -88,12 +93,12 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) {
/>
<Panel padding={true}>
<div className="row">
<div className="col-12 col-md-8">
<div className="col-12 col-xl-8">
<h1 className="mb-0">
<Skeleton />
</h1>
</div>
<div className="col-12 col-md-4">
<div className="col-12 col-xl-4">
<h1 className="mb-0">
<Skeleton />
</h1>
@@ -123,7 +128,10 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) {
{ property: "Type", value: mediaData.media_type },
{ property: "Created at", value: mediaData.created_at },
{ property: "Visibility", value: mediaData.creator_set_visibility },
{ property: "Model Used", value: "Model Name" },
{
property: "Model",
value: mediaData.model_used,
},
];
return (
@@ -134,13 +142,13 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) {
/>
<Panel padding={true}>
<div className="row g-4">
<div className="col-12 col-lg-8">
<div className="col-12 col-xl-8">
{renderMediaComponent(mediaData)}
</div>
<div className="col-12 col-lg-4">
<div className="d-flex">
<div className="col-12 col-xl-4">
<div className="d-flex mb-3 gap-2">
<Gravatar
size={50}
size={48}
username={mediaData.maybe_creator_user.display_name}
avatarIndex={
mediaData.maybe_creator_user.default_avatar.image_index
@@ -151,10 +159,12 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) {
/>
<div className="d-flex flex-column">
<Link
className="fw-medium"
to={`/profile/${mediaData.maybe_creator_user.display_name}`}
>
{mediaData.maybe_creator_user.display_name}
</Link>
{timeCreated}
</div>
</div>
<Accordion>
+8
View File
@@ -4570,6 +4570,7 @@ __metadata:
dependencies:
"@react-spring/types": ^9.7.3
craco: ^0.0.3
date-fns: 2.22.1
lerna: ^4.0.0
yarn: ^1.22.19
languageName: unknown
@@ -8966,6 +8967,13 @@ __metadata:
languageName: node
linkType: hard
"date-fns@npm:2.22.1":
version: 2.22.1
resolution: "date-fns@npm:2.22.1"
checksum: 7ff97cd605af50c02f341687c2cafd218839a1aace67965374989855a13f76dc4fe52e0e38c343c1ad1f8399787cb6839a0b14a669c44b30550c287300b1bb50
languageName: node
linkType: hard
"date-fns@npm:^2.22.1":
version: 2.28.0
resolution: "date-fns@npm:2.28.0"