Skip to content

Commit

Permalink
Merge pull request #785 from trash-lobster/next
Browse files Browse the repository at this point in the history
Next - adding multiview toolbar skeleton
  • Loading branch information
sphinxrave authored Dec 29, 2024
2 parents 5248323 + 4e2e7b2 commit fe9bc24
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 0 deletions.
42 changes: 42 additions & 0 deletions packages/react/src/components/multiview/LiveChannel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// import { useChannel } from "@/services/channel.service";
import { LiveChannelIcon } from "./LiveChannelIcon";
import { LiveStreamInfo } from "./LiveStreamInfo";
import { useState } from "react";

interface LiveChannelProps {
channelImgLink?: string;
channelName?: string;
altText?: string;
streamTitle?: string;
topicId?: string;
videoId?: string;
}

export function LiveChannel({
channelImgLink,
channelName,
altText,
streamTitle,
topicId,
videoId,
}: LiveChannelProps) {
const [isHover, setIsHover] = useState(false);

return (
<div>
<LiveChannelIcon
imageLink={channelImgLink}
channelName={channelName}
setIsHover={setIsHover}
/>
<LiveStreamInfo
thumbnailLink={`https://i.ytimg.com/vi/${videoId}/mqdefault.jpg`}
altText={altText}
streamTitle={streamTitle}
channelName={channelName}
topicId={topicId}
isVisible={isHover}
/>
</div>
);
}
31 changes: 31 additions & 0 deletions packages/react/src/components/multiview/LiveChannelIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Avatar, AvatarFallback, AvatarImage } from "@/shadcn/ui/avatar";
import { Dispatch, SetStateAction } from "react";

interface LiveChannelIconProps {
imageLink?: string;
channelName?: string;
setIsHover: Dispatch<SetStateAction<boolean>>;
}

export function LiveChannelIcon({
imageLink,
channelName,
setIsHover,
}: LiveChannelIconProps) {
return (
<div
draggable="true"
className="relative cursor-pointer"
onMouseEnter={() => setIsHover(true)}
onMouseLeave={() => setIsHover(false)}
>
<Avatar className="size-12">
<AvatarImage src={imageLink} alt={`${channelName} user icon`} />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<div className="absolute bottom-0 right-0 bg-red text-xs text-white">
12hr
</div>
</div>
);
}
48 changes: 48 additions & 0 deletions packages/react/src/components/multiview/LiveStreamInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { cn } from "@/lib/utils";

interface LiveStreamInfoProps {
thumbnailLink?: string;
altText?: string;
streamTitle?: string;
channelName?: string;
topicId?: string;
isVisible: boolean;
}

export function LiveStreamInfo({
thumbnailLink,
altText,
streamTitle,
channelName,
topicId,
isVisible,
}: LiveStreamInfoProps) {
return (
<div
className={cn(
// currently hardcoded a translate value, will investigate to find a better way
" absolute flex translate-x-[-118px] translate-y-2 flex-col rounded-md bg-base-6 opacity-80",
{
visible: isVisible,
invisible: !isVisible,
},
)}
>
<div className="relative flex w-full flex-col items-center px-4 py-2">
<img
className="h-auto w-64 rounded-lg"
src={thumbnailLink}
alt={altText}
/>
<p className="absolute left-4 top-2 z-30 bg-black px-1 py-0.5 text-white opacity-80">
{topicId}
</p>
</div>
<div>
<p>{streamTitle}</p>
<p>{channelName}</p>
<p>status</p>
</div>
</div>
);
}
79 changes: 79 additions & 0 deletions packages/react/src/components/multiview/Selector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { useEffect, useState } from "react";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/shadcn/ui/dropdown-menu";
import { defaultOrgs } from "../../store/org";
import { useLive } from "@/services/live.service";
import { LiveChannel } from "./LiveChannel";
import { cn } from "../../lib/utils";

/**
* ToDos:
* - select favourites
*/

export function Selector() {
// create a mock favourites object as an org
const Favorites: Org = {
name: "Favorites",
};
// based on what the selection is -> use different methods to render title card?
const [currentOrg, setCurrentOrg] = useState(Favorites);
const [liveChannels, setLiveChannels] = useState<Live[]>([]);
const liveStreams = useLive({ org: currentOrg.name });

useEffect(() => {
const data = liveStreams.data;
if (!data) return;
setLiveChannels(data);
console.log(data);
}, [liveStreams.data]);

const onSelect = (org: Org) => {
if (org.name === currentOrg.name) return;
setCurrentOrg(org);
setLiveChannels([]);
};

return (
<div className="flex w-full">
<DropdownMenu>
<DropdownMenuTrigger className="z-30 mx-2 flex min-h-8 w-48 shrink-0 items-center justify-between overflow-hidden rounded-md bg-base-2 pl-4 pr-2 hover:bg-primary-5 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary-7 active:scale-[97%] active:bg-primaryA-7 disabled:pointer-events-none disabled:opacity-50">
{currentOrg.name}
<div className="i-lucide:chevrons-down ml-2 inline-block h-4 w-4 shrink-0 align-middle opacity-50"></div>
</DropdownMenuTrigger>
<DropdownMenuContent className="z-30 w-48 bg-base-2">
{[Favorites, ...defaultOrgs].map((org) => {
return (
<DropdownMenuItem
className="cursor-pointer gap-1 py-2"
onClick={() => onSelect(org)}
>
{org.name}
</DropdownMenuItem>
);
})}
</DropdownMenuContent>
</DropdownMenu>
<div
id="live-channel-container"
className={cn("flex min-h-12 flex-nowrap gap-2 overflow-scroll", {})}
>
{liveChannels.map((live) => {
return (
<LiveChannel
key={live.id}
channelImgLink={live.channel.photo}
channelName={live.channel.name}
videoId={live.id}
topicId={live.topic_id!}
/>
);
})}
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function ToolButtonContainer() {
return <div className="w-48 bg-base-5">placeholder for buttons</div>;
}
15 changes: 15 additions & 0 deletions packages/react/src/components/multiview/Toolbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Selector } from "./Selector";
import { ToolButtonContainer } from "./ToolButtonContainer";

export function Toolbar() {
return (
<div className="flex w-full max-w-full flex-nowrap justify-between bg-base-2 p-2">
<div className="mr-2 w-3/5 shrink-0 grow-0 basis-auto">
<Selector />
</div>
<div className="ml-2 w-2/5 shrink-0 grow-0 basis-auto">
<ToolButtonContainer />
</div>
</div>
);
}
22 changes: 22 additions & 0 deletions packages/react/src/routes/multiview/multiview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Toolbar } from "@/components/multiview/Toolbar";
import { Helmet } from "react-helmet-async";

// multiview skeleton
// selection bar at the top to change between orgs and allow url insertion
// grid page for drag and drop

export function Multiview() {
return (
<>
<Helmet>
<title>Multiview - Holodex</title>
</Helmet>
<div
id="multiview-banner"
className="sticky top-0 z-20 flex justify-start gap-2 rounded-lg bg-base-2 p-2 text-base-11 transition-all md:mx-8 md:px-2"
>
<Toolbar />
</div>
</>
);
}
6 changes: 6 additions & 0 deletions packages/react/src/routes/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ const ResetClientPage = lazy(() =>
import("./debug").then((module) => ({ default: module.ResetClientPage })),
);
const Playlist = lazy(() => import("./playlist"));
const Multiview = lazy(() =>
import("./multiview/multiview").then((module) => ({
default: module.Multiview,
})),
);

const Search = lazy(() =>
import("./search").then((module) => ({ default: module.Search })),
Expand Down Expand Up @@ -158,6 +163,7 @@ export const routes = (
<Route path="contact" Component={AboutContact} />
<Route path="privacy" Component={AboutPrivacy} />
</Route>
<Route path="multiview" Component={Multiview} />
<Route path="kitchensink" Component={Kitchensink} />
<Route path="login" Component={Login} />
<Route path="tlclient" element={<div>Translation Client</div>} />
Expand Down

0 comments on commit fe9bc24

Please sign in to comment.