Grouped components into folders

This commit is contained in:
strNophix 2022-10-16 16:26:24 +02:00
parent ea603804a2
commit 38f3caa524
20 changed files with 177 additions and 242 deletions

View File

@ -1,38 +0,0 @@
import { ArrowLeftIcon } from '@heroicons/react/24/outline';
import Button from './Button';
import NavBar from './NavBar';
import SideNavChannel from './SideNavChannel';
import streamData from '../placeholder/GetStreams';
import { NextPage } from 'next';
import Link from 'next/link';
const BrowseLayout: NextPage = ({children}) => {
return (
<div className="font-inter flex flex-col h-screen text-gray-100">
<NavBar />
<main className="flex-1 flex flex-row overflow-hidden">
<div className="bg-neutral-800 w-60 flex flex-col">
<div className="flex flex-row justify-between p-2 items-center">
<p className="uppercase font-semibold text-sm">Trending channels</p>
<Button variant="subtle" className="p-2">
<ArrowLeftIcon className="w-4 h-4" />
</Button>
</div>
<ul className="flex-1 overflow-scrollbar">
{streamData.data.map((stream) => (
<li key={stream.id}>
<Link href={`/${stream.user_login}`} passHref={true}>
<SideNavChannel stream={stream} />
</Link>
</li>
))}
</ul>
</div>
{children}
</main>
</div>
);
}
export default BrowseLayout;

View File

@ -1,65 +0,0 @@
import { UserIcon } from '@heroicons/react/24/outline';
import { FC, useState } from 'react';
import Button from './Button';
import Input from './Input';
import LoginModal from './LoginModal';
const NavBar: FC = () => {
const [showLogin, setShowLogin] = useState(false);
const [showTab, setShowTab] = useState(0);
const showLoginTab = () => {
setShowTab(0);
setShowLogin(true);
};
const showSignupTab = () => {
setShowTab(1);
setShowLogin(true);
};
return (
<nav className="bg-zinc-800 w-screen font-semibold border-b border-b-black">
<div className="flex flex-row justify-between items-center mx-2">
<div className="basis-1/4">
<ul className="flex flex-row space-x-8 items-center">
<li>
<img src="./assets/images/logo.png" className="w-8 h-8" alt="logo" />
</li>
<li>
<p className="text-lg">Browse</p>
</li>
</ul>
</div>
<div className="basis-2/4">
<div className="flex flex-row space-x-3 items-center justify-center">
<Input className=" w-72 my-2 p-2" placeholder="Search" />
</div>
</div>
<div className="basis-1/4">
<ul className="justify-end flex flex-row space-x-3 items-center">
<li>
<Button className="text-sm px-3 py-2 bg-neutral-700" onClick={showLoginTab}>
Log In
</Button>
</li>
<li>
<Button className="text-sm px-3 py-2 bg-violet-500" onClick={showSignupTab}>
Sign Up
</Button>
</li>
<li>
<Button variant="subtle" className="p-1">
<UserIcon className="h-5 w-5 inline-block" />
</Button>
</li>
</ul>
</div>
</div>
<LoginModal isOpen={showLogin} defaultPage={showTab} onClose={() => setShowLogin(false)} />
</nav>
);
};
export default NavBar;

View File

@ -1,28 +0,0 @@
import { FC } from 'react';
import { Stream } from '../types';
import { numFormatter } from '../utils/format';
interface SideNavChannelProps {
stream: Stream;
}
const SideNavChannel: FC<SideNavChannelProps> = ({ stream }) => {
return (
<div className="flex flex-row px-3 py-2 text-sm leading-4 space-x-2 hover:bg-neutral-700/40 cursor-pointer">
<img className="rounded-full w-8 h-8" src={stream.thumbnail_url} alt="avatar" />
<div className="flex flex-col flex-1">
<div className="flex flex-row justify-between">
<div className="font-bold">{stream.user_name}</div>
<div className="space-x-1 flex flex-row items-center">
<div className="w-2 h-2 bg-red-600 rounded-full inline-block" />
<span>{numFormatter.format(stream.viewer_count)}</span>
</div>
</div>
<div className="text-gray-300">{stream.game_name}</div>
</div>
</div>
);
};
export default SideNavChannel;

View File

@ -1,7 +1,7 @@
/* eslint-disable react/display-name */
import { forwardRef, ReactNode } from "react"
import Input from "./Input"
import Input from "../Input"
interface FormFieldProps extends React.ComponentPropsWithoutRef<"input"> {
label?: string

View File

@ -0,0 +1,13 @@
import NavBar from "../nav/NavBar"
import { NextPage } from "next"
const BrowseLayout: NextPage = ({ children }) => {
return (
<div className="font-inter flex flex-col h-screen text-gray-100">
<NavBar />
<main className="flex-1 flex flex-row overflow-hidden">{children}</main>
</div>
)
}
export default BrowseLayout

View File

@ -1,30 +1,30 @@
import { FC } from 'react';
import { useForm, SubmitHandler } from 'react-hook-form';
import { FC } from "react"
import { useForm, SubmitHandler } from "react-hook-form"
import FormField from './FormField';
import InlineLink from './InlineLink';
import SubmitButton from './SubmitButton';
import FormField from "../common/form/FormField"
import InlineLink from "../common/InlineLink"
import SubmitButton from "../common/form/SubmitButton"
interface LoginFormValues {
username: string;
password: string;
username: string
password: string
}
const LoginForm: FC = () => {
const { register, handleSubmit } = useForm<LoginFormValues>();
const onSubmit: SubmitHandler<LoginFormValues> = (data) => console.log(data);
const { register, handleSubmit } = useForm<LoginFormValues>()
const onSubmit: SubmitHandler<LoginFormValues> = (data) => console.log(data)
return (
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
<FormField
label="Username"
className="py-2 px-2 outline-2 w-full"
{...register('username')}
{...register("username")}
/>
<FormField
label="Password"
type="password"
{...register('password')}
{...register("password")}
className="py-2 px-2 outline-2 w-full"
bottomElement={
<InlineLink to="#" className="block mt-2">
@ -34,7 +34,7 @@ const LoginForm: FC = () => {
/>
<SubmitButton className="w-full" value="Log In" />
</form>
);
};
)
}
export default LoginForm;
export default LoginForm

View File

@ -1,14 +1,14 @@
import { Dialog, Tab } from '@headlessui/react';
import { FC, useEffect, useRef } from 'react';
import { Dialog, Tab } from "@headlessui/react"
import { FC } from "react"
import LoginForm from './LoginForm';
import LoginModalTab from './LoginModalTab';
import SignupForm from './SignupForm';
import LoginForm from "./LoginForm"
import LoginModalTab from "./LoginModalTab"
import SignupForm from "./SignupForm"
export interface LoginModelProps {
isOpen: boolean;
onClose: () => any;
defaultPage?: number;
isOpen: boolean
onClose: () => any
defaultPage?: number
}
const LoginModal: FC<LoginModelProps> = ({ defaultPage, isOpen, onClose }) => {
@ -18,16 +18,25 @@ const LoginModal: FC<LoginModelProps> = ({ defaultPage, isOpen, onClose }) => {
<Dialog.Panel className="bg-zinc-900 text-gray-100 w-[420px] rounded-md py-12 px-6">
<div className="flex flex-row items-center justify-center">
<Dialog.Title className="text-xl">
<img src="./assets/images/logo.png" className="inline w-12 h-12" alt="logo" /> Log in to twitch-clone
<img
src="./assets/images/logo.png"
className="inline w-12 h-12"
alt="logo"
/>{" "}
Log in to twitch-clone
</Dialog.Title>
</div>
<Tab.Group defaultIndex={defaultPage}>
<Tab.List className="space-x-4 border-b border-b-neutral-100/40 mt-4">
<Tab>
{({ selected }) => <LoginModalTab selected={selected}>Log In</LoginModalTab>}
{({ selected }) => (
<LoginModalTab selected={selected}>Log In</LoginModalTab>
)}
</Tab>
<Tab>
{({ selected }) => <LoginModalTab selected={selected}>Sign Up</LoginModalTab>}
{({ selected }) => (
<LoginModalTab selected={selected}>Sign Up</LoginModalTab>
)}
</Tab>
</Tab.List>
<Tab.Panels className="mt-4">
@ -41,7 +50,8 @@ const LoginModal: FC<LoginModelProps> = ({ defaultPage, isOpen, onClose }) => {
</Tab.Group>
</Dialog.Panel>
</div>
</Dialog>)
};
</Dialog>
)
}
export default LoginModal;
export default LoginModal

View File

@ -1,16 +1,15 @@
import { zodResolver } from "@hookform/resolvers/zod"
import { SelfServiceRegistrationFlow } from "@ory/client"
import { useRouter } from "next/router"
import { useMemo } from "react"
import { FC, useEffect, useState } from "react"
import { SubmitHandler, useForm } from "react-hook-form"
import { z } from "zod"
import ory from "../services/ory"
import ory from "../../services/ory"
import FormField from "./FormField"
import InlineLink from "./InlineLink"
import Input from "./Input"
import SubmitButton from "./SubmitButton"
import FormField from "../common/form/FormField"
import InlineLink from "../common/InlineLink"
import Input from "../common/Input"
import SubmitButton from "../common/form/SubmitButton"
const PASSWORD_REGEX =
/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$ %^&*-]).{8,64}$/

View File

@ -1,6 +1,6 @@
import { FC } from 'react';
import { FC } from "react"
import ChatBadge from './ChatBadge';
import ChatBadge from "./ChatBadge"
const ChatMessage: FC = () => {
return (
@ -19,7 +19,7 @@ const ChatMessage: FC = () => {
/>
</span>
</p>
);
};
)
}
export default ChatMessage;
export default ChatMessage

View File

@ -0,0 +1,71 @@
import { UserIcon } from "@heroicons/react/24/outline"
import { FC, useState } from "react"
import Button from "../common/Button"
import Input from "../common/Input"
import LoginModal from "../login/LoginModal"
const NavBar: FC = () => {
const [showLogin, setShowLogin] = useState(false)
const [showTab, setShowTab] = useState(0)
const showLoginTab = () => {
setShowTab(0)
setShowLogin(true)
}
const showSignupTab = () => {
setShowTab(1)
setShowLogin(true)
}
return (
<nav className="bg-zinc-800 w-screen font-semibold border-b border-b-black">
<div className="flex flex-row justify-between items-center h-12 mx-2">
<div>
<ul className="flex flex-row space-x-8 items-center">
<li>
<img
src="./assets/images/logo.png"
className="w-8 h-8"
alt="logo"
/>
</li>
</ul>
</div>
<div>
<ul className="justify-end flex flex-row space-x-3 items-center">
<li>
<Button
className="text-sm px-3 py-2 bg-neutral-700"
onClick={showLoginTab}
>
Log In
</Button>
</li>
<li>
<Button
className="text-sm px-3 py-2 bg-violet-500"
onClick={showSignupTab}
>
Sign Up
</Button>
</li>
<li>
<Button variant="subtle" className="p-[0.4rem]">
<UserIcon className="h-5 w-5 inline-block" />
</Button>
</li>
</ul>
</div>
</div>
<LoginModal
isOpen={showLogin}
defaultPage={showTab}
onClose={() => setShowLogin(false)}
/>
</nav>
)
}
export default NavBar

View File

@ -1,68 +1,42 @@
import { ArrowRightIcon, HeartIcon, UserIcon } from '@heroicons/react/24/outline';
import Button from '../../components/Button';
import ChatMessage from '../../components/ChatMessage';
import Input from '../../components/Input';
import { numFormatter } from '../../utils/format';
import streams from '../../placeholder/GetStreams';
import { NextPage } from 'next';
import BrowseLayout from '../../components/BrowseLayout';
import Button from "../../components/common/Button"
import ChatMessage from "../../components/message/ChatMessage"
import Input from "../../components/common/Input"
import streams from "../../placeholder/GetStreams"
import { NextPage } from "next"
import BrowseLayout from "../../components/layout/BrowseLayout"
const ChannelPage: NextPage = () => {
const stream = streams.data[1];
const stream = streams.data[1]
return (
<BrowseLayout>
<div className="flex-1 flex flex-row">
<div className="bg-neutral-900 flex-1">
<div className="w-full h-auto aspect-video bg-red-200 " />
<div className="flex flex-row p-4 space-x-3">
<div className="w-20 h-20 bg-yellow-300 rounded-full" />
<div className="flex-1">
<div className="flex flex-row justify-between items-center">
<div className="font-bold">{stream.user_name}</div>
<div>
<Button className="h-8 w-10">
<HeartIcon className="text-gray-100 h-5 w-5 mx-auto" />
</Button>
</div>
</div>
<div className="flex flex-row justify-between items-center">
<div className="space-y-1">
<div className="font-bold">{stream.title}</div>
<div className="text-violet-400">{stream.game_name}</div>
</div>
<div className="flex flex-row items-center text-sm space-x-3">
<span>
<UserIcon className="h-5 w-5 inline-block" />
<span>{numFormatter.format(stream.viewer_count)}</span>
</span>
<span>{stream.started_at}</span>
</div>
<div className="flex-1 flex flex-row">
<div className="bg-neutral-900 flex-1 flex flex-col">
<div className="w-full bg-red-200 flex-1" />
<div className="flex flex-row p-2 items-center justify-between">
<div className="flex flex-row items-center space-x-3">
<span className="w-8 h-8 bg-yellow-300 rounded-full" />
<span className="font-bold">{stream.user_name}</span>
</div>
<div>1:14:32</div>
</div>
</div>
<div className="bg-zinc-900 w-80 border-l border-l-zinc-700 flex flex-col">
<div className="flex flex-row justify-center items-center border-b border-b-zinc-700 p-2 h-12">
<p className="uppercase font-semibold text-sm">Stream Chat</p>
</div>
<div className="flex-1 overflow-scrollbar">
{new Array(60).fill(0).map((_, i) => (
<ChatMessage key={i} />
))}
</div>
<div className="m-2">
<Input className="w-full p-2" placeholder="Send a message" />
</div>
</div>
</div>
<div className="bg-zinc-900 w-80 border-l border-l-zinc-700 flex flex-col">
<div className="flex flex-row justify-between items-center border-b border-b-zinc-700 p-2">
<Button variant="subtle" className="p-2">
<ArrowRightIcon className="w-4 h-4" />
</Button>
<p className="uppercase font-semibold text-sm">Stream Chat</p>
<div className="w-5" />
</div>
<div className="flex-1 overflow-scrollbar">
{new Array(60).fill(0).map((_, i) => (
<ChatMessage key={i} />
))}
</div>
<div className="m-2">
<Input className="w-full p-2" placeholder="Send a message" />
</div>
</div>
</div>
</BrowseLayout>
);
)
}
export default ChannelPage;
export default ChannelPage

View File

@ -1,7 +1,7 @@
import { categories } from '../../placeholder/SearchCategories';
import { categories } from "../../placeholder/SearchCategories"
function ChannelPage() {
const category = categories.data[0];
const category = categories.data[0]
return (
<div className="flex-1 flex flex-row">
<div className="bg-neutral-900 flex-1 text-gray-100">
@ -20,7 +20,7 @@ function ChannelPage() {
</div>
</div>
</div>
);
)
}
export default ChannelPage;
export default ChannelPage

View File

@ -1,13 +1,13 @@
import { NextPage } from 'next';
import { NextPage } from "next"
import LoginModal from '../components/LoginModal';
import LoginModal from "../components/login/LoginModal"
const LoginPage: NextPage = () => {
return (
<div className="bg-neutral-900 w-screen h-screen">
<LoginModal isOpen={true} defaultPage={0} onClose={() => {}} />
</div>
);
};
)
}
export default LoginPage;
export default LoginPage

View File

@ -1,13 +1,12 @@
import { NextPage } from 'next';
import LoginModal from '../components/LoginModal';
import { NextPage } from "next"
import LoginModal from "../components/login/LoginModal"
const SignupPage: NextPage = () => {
return (
<div className="bg-neutral-900 w-screen h-screen">
<LoginModal isOpen={true} defaultPage={1} onClose={() => {}} />
</div>
);
};
)
}
export default SignupPage;
export default SignupPage