initial ratings/likes progress

This commit is contained in:
Victor committed 2024-01-05 00:19:46 -05:00
1 parent d0018ea4e8
commit b64fc69d83
11 files changed
+156 -178

No files matched your search

@@ -0,0 +1,23 @@
import MakeRequest from "../MakeRequest";
export interface Rating {
entity_token: string,
entity_type: string,
rating_value: string
}
export interface GetRatingsRequest {}
export interface GetRatingsResponse {
success: boolean,
ratings?: Rating[]
}
export interface GetRatingsQueries {
tokens: string[],
}
export const GetRatings = MakeRequest<string, GetRatingsRequest, GetRatingsResponse, GetRatingsQueries>({
method: "GET",
routingFunction: () => `/v1/user_rating/batch`,
});
@@ -17,18 +17,20 @@ interface AudioCardProps {
bookmarks: any;
data: any;
origin?: string;
type: "media" | "weights";
ratings: any;
showCreator?: boolean;
showCover?: boolean;
type: "media" | "weights";
}
export default function AudioCard({
bookmarks,
data,
origin = "",
type,
ratings,
showCreator,
showCover,
type,
}: AudioCardProps) {
const linkUrl =
type === "media"
@@ -43,11 +45,6 @@ export default function AudioCard({
const timeAgo = useTimeAgo(data.created_at);
const handleLike = async () => {
console.log(`The item is now ${data.isLiked ? "liked" : "not liked"}.`);
return true; // temporary, replace with like function
};
const { label: weightBadgeLabel, color: weightBadgeColor } =
useWeightTypeInfo(
data.weight_type || data.details?.maybe_weight_data?.weight_type
@@ -126,7 +123,12 @@ export default function AudioCard({
)}
<div>
<LikeButton onToggle={handleLike} likeCount={data.like || 0} />
<LikeButton {...{
entityToken: data.token,
entityType: "media_file",
likeCount: data.likes,
onToggle: ratings.toggle
}} />
</div>
</div>
</>
@@ -184,7 +186,12 @@ export default function AudioCard({
)}
<div>
<LikeButton onToggle={handleLike} likeCount={data.likes} />
<LikeButton {...{
entityToken: data.weight_token,
entityType: "model_weight",
likeCount: data.likes,
onToggle: ratings.toggle
}} />
</div>
<BookmarkButton
{...{
@@ -15,16 +15,18 @@ interface ImageCardProps {
bookmarks: any;
data: any;
origin?: string;
type: "media" | "weights";
ratings: any;
showCreator?: boolean;
type: "media" | "weights";
}
export default function ImageCard({
bookmarks,
data,
origin = "",
type,
showCreator,
ratings,
type
}: ImageCardProps) {
const linkUrl =
type === "media"
@@ -39,11 +41,6 @@ export default function ImageCard({
const timeAgo = useTimeAgo(data.created_at);
const handleLike = async () => {
console.log(`The item is now ${data.isLiked ? "liked" : "not liked"}.`);
return true; // temporary will be replaced with like function
};
const { label: weightBadgeLabel, color: weightBadgeColor } =
useWeightTypeInfo(
data.weight_type || data.details?.maybe_weight_data?.weight_type
@@ -122,7 +119,12 @@ export default function ImageCard({
)}
<div>
<LikeButton onToggle={handleLike} likeCount={data.likes} />
<LikeButton {...{
entityToken: data.token,
entityType: "media_file",
likeCount: data.likes,
onToggle: ratings.toggle
}} />
</div>
</div>
</div>
@@ -186,7 +188,12 @@ export default function ImageCard({
)}
<div>
<LikeButton onToggle={handleLike} likeCount={data.likes} />
<LikeButton {...{
entityToken: data.weight_token,
entityType: "model_weight",
likeCount: data.likes,
onToggle: ratings.toggle
}} />
</div>
<BookmarkButton
{...{
@@ -13,11 +13,12 @@ import { Link } from "react-router-dom";
interface VideoCardProps {
data: any;
origin?: string;
type: "media" | "weights";
ratings: any;
showCreator?: boolean;
type: "media" | "weights";
}
export default function VideoCard({ data, origin = "", type, showCreator }: VideoCardProps) {
export default function VideoCard({ data, origin = "", ratings, showCreator, type }: VideoCardProps) {
const linkUrl =
type === "media" ? `/media/${data.token}` : `/weight/${data.weight_token}`;
@@ -27,11 +28,6 @@ export default function VideoCard({ data, origin = "", type, showCreator }: Vide
const timeAgo = useTimeAgo(data.created_at);
const handleLike = async () => {
console.log(`The item is now ${data.isLiked ? "liked" : "not liked"}.`);
return true; // temporary, replace with like function
};
const videoLink = new BucketConfig().getGcsUrl(data.public_bucket_path);
return (
@@ -86,10 +82,12 @@ export default function VideoCard({ data, origin = "", type, showCreator }: Vide
)}
<div>
<LikeButton
onToggle={handleLike}
likeCount={data.likes}
/>
<LikeButton {...{
entityToken: data.token,
entityType: "media_file",
likeCount: data.likes,
onToggle: ratings.toggle
}} />
</div>
</div>
</div>
@@ -132,11 +130,13 @@ export default function VideoCard({ data, origin = "", type, showCreator }: Vide
</h6>
<p className="fs-7 opacity-75">{timeAgo}</p>
<div className="mt-2" onClick={handleInnerClick}>
<LikeButton
onToggle={handleLike}
likeCount={data.likes}
overlay={true}
/>
<LikeButton {...{
entityToken: data.weight_token,
entityType: "model_weight",
likeCount: data.likes,
onToggle: ratings.toggle,
overlay: true
}} />
</div>
</div>
</div>
@@ -26,15 +26,16 @@ export default function LikeButton({
overlay,
large,
}: LikeButtonProps) {
const [isToggled, setIsToggled] = useState(initialToggled);
const isToggled = initialToggled; // toggled value managed externally via useRatings, this may change
// const [isToggled, setIsToggled] = useState(initialToggled);
const [isLoading, setIsLoading] = useState(false);
const handleClick = async (event: React.MouseEvent) => {
event.preventDefault();
event.stopPropagation();
setIsLoading(true);
// setIsLoading(true);
onToggle(entityToken, entityType).then((isToggled: boolean) => {
setIsToggled(isToggled);
// setIsToggled(isToggled);
setIsLoading(false);
});
// try {
@@ -1,11 +1,46 @@
import { useState } from 'react';
import { FetchStatus } from "@storyteller/components/src/api/_common/SharedFetchTypes";
import { GetRatings, GetRatingsResponse } from "@storyteller/components/src/api/user_ratings/GetRatings";
import { SetRating, SetRatingResponse } from "@storyteller/components/src/api/user_ratings/SetRating";
interface Props {
value?: any;
}
// interface Props {
// value?: any
// }
export default function useRatings({ value }: Props) {
const [status, statusSet] = useState(FetchStatus.ready);
return { status, statusSet };
export default function useRatings() {
// const [library, librarySet] = useState({});
const [baseList, baseListSet] = useState<any[]>([]);
const [toggleStatus, toggleStatusSet] = useState(FetchStatus.ready);
const library = baseList.reduce((obj: any, current: any) => {
return { ...obj, [current.entity_token]: current.token }
},{});
const gather = (res: any) => {
let tokens = res.results.map((item: any) => item.token);
console.log("💧", tokens);
GetRatings("",{},{ tokens }).then((res: GetRatingsResponse) => {
if (res.success && res.ratings) {
console.log("🪙",res);
baseListSet(res.ratings);
}
});
};
const toggle = (token: string, entityType: string) => {
let inLibrary = library[token];
toggleStatusSet(FetchStatus.in_progress);
console.log("⏳ toggling bookmark ...",{ token, entityType });
SetRating("",{
entity_token: token,
entity_type: entityType,
rating_value: !inLibrary || inLibrary.rating_value === "neutral" ? "positive" : "neutral"
}).then(( res: SetRatingResponse ) => {
toggleStatusSet(FetchStatus.ready);
console.log("👍 like toggled",res);
});
};
return { gather, toggleStatus, toggleStatusSet, toggle };
};
@@ -1,20 +1,18 @@
import React, { useEffect, useRef, useState } from "react";
import MasonryGrid from "components/common/MasonryGrid/MasonryGrid";
import AudioCard from "components/common/Card/AudioCard";
import MediaCards from "components/common/Card/MediaCards";
import { Link } from "react-router-dom";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronRight } from "@fortawesome/pro-solid-svg-icons";
import { MediaFile } from "@storyteller/components/src/api/media_files/GetMedia";
import { useBookmarks } from "hooks";
import { useBookmarks, useRatings } from "hooks";
import { ListFeaturedMediaFiles } from "@storyteller/components/src/api/media_files/ListFeaturedMediaFiles";
import { FetchStatus } from "@storyteller/components/src/api/_common/SharedFetchTypes";
import SkeletonCard from "components/common/Card/SkeletonCard";
import ImageCard from "components/common/Card/ImageCard";
import VideoCard from "components/common/Card/VideoCard";
export default function FeaturedTab() {
const bookmarks = useBookmarks();
const ratings = useRatings();
const gridContainerRef = useRef<HTMLDivElement | null>(null);
const [list, listSet] = useState<MediaFile[]>([]);
// const [showMasonryGrid, setShowMasonryGrid] = useState(true);
@@ -61,57 +59,16 @@ export default function FeaturedTab() {
gridRef={gridContainerRef}
onLayoutComplete={() => console.log("Layout complete!")}
>
{ list.map((data: any, index: number) => {
let card;
switch (data.media_type) {
case "audio":
card = (
<AudioCard
{...{
bookmarks,
data,
type: "media",
showCreator: true,
}}
/>
);
break;
case "image":
card = (
<ImageCard
{...{
bookmarks,
data,
type: "media",
showCreator: true,
}}
/>
);
break;
case "video":
card = (
<VideoCard
{...{
bookmarks,
data,
type: "media",
showCreator: true,
}}
/>
);
break;
default:
card = <div>Unsupported media type</div>;
}
return (
<div
key={index}
className="col-12 col-sm-6 col-xl-4 grid-item"
>
{card}
</div>
);
})}
{ list.map((data: any, key: number) => {
let props = { bookmarks, data, origin, ratings, type: "media" };
return <div {...{
className: "col-12 col-sm-6 col-xl-4 grid-item",
key
}}>
<MediaCards {...{ type: data.media_type, props }} />
</div>;
}) }
</MasonryGrid>
)}
</>
@@ -1,9 +1,7 @@
import React, { useRef, useState } from "react";
import { useLocation } from "react-router-dom";
import MasonryGrid from "components/common/MasonryGrid/MasonryGrid";
import AudioCard from "components/common/Card/AudioCard";
import ImageCard from "components/common/Card/ImageCard";
import VideoCard from "components/common/Card/VideoCard";
import MediaCards from "components/common/Card/MediaCards";
import { TempSelect } from "components/common";
import {
faArrowDownWideShort,
@@ -13,7 +11,7 @@ import AudioPlayerProvider from "components/common/AudioPlayer/AudioPlayerContex
import SkeletonCard from "components/common/Card/SkeletonCard";
import { ListMediaFiles } from "@storyteller/components/src/api/media_files/ListMediaFiles";
import { MediaFile } from "@storyteller/components/src/api/media_files/GetMedia";
import { useBookmarks, useLazyLists } from "hooks";
import { useBookmarks, useLazyLists, useRatings } from "hooks";
import InfiniteScroll from "react-infinite-scroll-component";
import prepFilter from "resources/prepFilter";
@@ -21,6 +19,7 @@ export default function MediaTab() {
const { search } = useLocation();
const urlQueries = new URLSearchParams(search);
const bookmarks = useBookmarks();
const ratings = useRatings();
const gridContainerRef = useRef<HTMLDivElement | null>(null);
const [weightType, weightTypeSet] = useState(
urlQueries.get("maybe_scoped_weight_type") || "all"
@@ -116,58 +115,16 @@ export default function MediaTab() {
<MasonryGrid
gridRef={gridContainerRef}
onLayoutComplete={() => console.log("Layout complete!")}
>
{media.list.map((data: any, index: number) => {
let card;
switch (data.media_type) {
case "audio":
card = (
<AudioCard
{...{
bookmarks,
data,
type: "media",
showCreator: true,
}}
/>
);
break;
case "image":
card = (
<ImageCard
{...{
bookmarks,
data,
type: "media",
showCreator: true,
}}
/>
);
break;
case "video":
card = (
<VideoCard
{...{
bookmarks,
data,
type: "media",
showCreator: true,
}}
/>
);
break;
default:
card = <div>Unsupported media type</div>;
}
return (
<div
key={index}
className="col-12 col-sm-6 col-xl-4 grid-item"
>
{card}
</div>
);
})}
> { media.list.map((data: any, key: number) => {
let props = { bookmarks, data, origin, ratings, type: "media" };
return <div {...{
className: "col-12 col-sm-6 col-xl-4 grid-item",
key
}}>
<MediaCards {...{ type: data.media_type, props }} />
</div>;
}) }
</MasonryGrid>
)}
</>
@@ -9,7 +9,7 @@ import {
} from "@fortawesome/pro-solid-svg-icons";
import Pagination from "components/common/Pagination";
import { useBookmarks, useListContent } from "hooks";
import { useBookmarks, useListContent, useRatings } from "hooks";
import { GetBookmarksByUser } from "@storyteller/components/src/api/bookmarks/GetBookmarksByUser";
import WeightsCards from "components/common/Card/WeightsCards";
import prepFilter from "resources/prepFilter";
@@ -18,6 +18,7 @@ export default function BookmarksTab({ username }: { username: string }) {
const { pathname: origin, search } = useLocation();
const urlQueries = new URLSearchParams(search);
const bookmarks = useBookmarks();
const ratings = useRatings();
const gridContainerRef = useRef<HTMLDivElement | null>(null);
const [showMasonryGrid, setShowMasonryGrid] = useState(true);
const [weightType, weightTypeSet] = useState(
@@ -205,13 +206,7 @@ export default function BookmarksTab({ username }: { username: string }) {
onLayoutComplete={() => console.log("Layout complete!")}
>
{dataList.map((data: any, key: number) => {
let weightProps = {
bookmarks,
data,
origin,
type: "weights",
showCreator: true,
};
let weightProps = { bookmarks, data, origin, ratings, showCreator: true, type: "weights" };
// let mediaProps = {
// bookmarks,
@@ -13,34 +13,35 @@ import Pagination from "components/common/Pagination";
import { GetMediaByUser } from "@storyteller/components/src/api/media_files/GetMediaByUser";
import { MediaFile } from "@storyteller/components/src/api/media_files/GetMedia";
import { useBookmarks, useListContent } from "hooks";
import { useBookmarks, useListContent, useRatings } from "hooks";
import prepFilter from "resources/prepFilter";
export default function MediaTab({ username }: { username: string }) {
const { pathname: origin, search } = useLocation();
const urlQueries = new URLSearchParams(search);
const bookmarks = useBookmarks();
const ratings = useRatings();
const gridContainerRef = useRef<HTMLDivElement | null>(null);
const [showMasonryGrid, setShowMasonryGrid] = useState(true);
const [mediaType, mediaTypeSet] = useState(
urlQueries.get("filter_media_type") || "all"
);
const [list, listSet] = useState<MediaFile[]>([]);
// const resetMasonryGrid = () => {
// setShowMasonryGrid(false);
// setTimeout(() => setShowMasonryGrid(true), 10);
// };
const media = useListContent({
addQueries: {
page_size: 24,
...prepFilter(mediaType, "filter_media_type"),
},
addSetters: { mediaTypeSet },
debug: "profile media",
fetcher: GetMediaByUser,
list,
listSet,
onInputChange: () => setShowMasonryGrid(false),
onSuccess: () => setShowMasonryGrid(true),
onSuccess: (res) => {
ratings.gather(res);
setShowMasonryGrid(true);
},
requestList: true,
urlParam: username,
});
@@ -114,7 +115,7 @@ export default function MediaTab({ username }: { username: string }) {
onLayoutComplete={() => console.log("Layout complete!")}
>
{media.list.map((data: MediaFile, key: number) => {
let props = { bookmarks, data, origin, type: "media" };
let props = { bookmarks, data, origin, ratings, type: "media" };
return (
<div
{...{
@@ -7,7 +7,7 @@ import {
faFilter,
} from "@fortawesome/pro-solid-svg-icons";
import Pagination from "components/common/Pagination";
import { useBookmarks, useListContent } from "hooks";
import { useBookmarks, useListContent, useRatings } from "hooks";
import { GetWeightsByUser } from "@storyteller/components/src/api/weights/GetWeightsByUser";
import { TempSelect } from "components/common";
import SkeletonCard from "components/common/Card/SkeletonCard";
@@ -34,6 +34,7 @@ export default function WeightsTab({ username }: { username: string }) {
const [vc, vcSet] = useState("all");
const [showMasonryGrid, setShowMasonryGrid] = useState(true);
const bookmarks = useBookmarks();
const ratings = useRatings();
const [list, listSet] = useState<any[]>([]);
const weights = useListContent({
addQueries: {
@@ -193,13 +194,7 @@ export default function WeightsTab({ username }: { username: string }) {
onLayoutComplete={() => console.log("Layout complete!")}
>
{weights.list.map((data: any, key: number) => {
let props = {
bookmarks,
data,
origin,
showCreator: true,
type: "weights",
};
let props = { bookmarks, data, origin, ratings, showCreator: true, type: "weights" };
return (
<div