Initial commit

This commit is contained in:
2024-09-14 23:38:24 -04:00
parent e48ab0aa6e
commit ce046c2062
25 changed files with 2263 additions and 83 deletions

20
src/app/dash/layout.tsx Normal file
View File

@@ -0,0 +1,20 @@
import { type PropsWithChildren } from "react"
import { Sidebar } from "~/components/sidebar"
import { inter } from "../layout"
import "~/styles/globals.css"
export default function RootLayout({ children }: PropsWithChildren) {
return (
<html lang="en">
<body className={`font-sans ${inter.variable}`}>
<div className="flex h-screen">
<Sidebar />
<main className="flex-1 overflow-y-auto">
{children}
</main>
</div>
</body>
</html>
)
}

54
src/app/dash/page.tsx Normal file
View File

@@ -0,0 +1,54 @@
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '~/components/ui/card';
import { Button } from '~/components/ui/button';
const HomePage: React.FC = () => {
return (
<div className="min-h-screen bg-gradient-to-b from-blue-100 to-white pt-14 lg:pt-0">
<div className="container mx-auto px-4 py-16">
<header className="text-center mb-16">
<h1 className="text-5xl font-bold mb-4 text-blue-800">Welcome to the HRIStudio Dashboard!</h1>
<p className="text-xl text-gray-600 max-w-3xl mx-auto">
Manage your Human-Robot Interaction projects and experiments
</p>
</header>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<Card className="bg-white shadow-lg">
<CardHeader>
<CardTitle className="text-2xl font-semibold text-blue-700">Projects</CardTitle>
<CardDescription>Manage your HRI projects</CardDescription>
</CardHeader>
<CardContent>
<p className="mb-4">Create, edit, and analyze your HRI projects.</p>
<Button className="bg-blue-600 hover:bg-blue-700 text-white">View Projects</Button>
</CardContent>
</Card>
<Card className="bg-white shadow-lg">
<CardHeader>
<CardTitle className="text-2xl font-semibold text-blue-700">Experiments</CardTitle>
<CardDescription>Design and run experiments</CardDescription>
</CardHeader>
<CardContent>
<p className="mb-4">Set up, conduct, and analyze HRI experiments.</p>
<Button className="bg-green-600 hover:bg-green-700 text-white">New Experiment</Button>
</CardContent>
</Card>
<Card className="bg-white shadow-lg">
<CardHeader>
<CardTitle className="text-2xl font-semibold text-blue-700">Data Analysis</CardTitle>
<CardDescription>Analyze your research data</CardDescription>
</CardHeader>
<CardContent>
<p className="mb-4">Visualize and interpret your HRI research data.</p>
<Button className="bg-purple-600 hover:bg-purple-700 text-white">Analyze Data</Button>
</CardContent>
</Card>
</div>
</div>
</div>
);
};
export default HomePage;

View File

@@ -1,20 +1,31 @@
import "~/styles/globals.css";
import { ClerkProvider } from '@clerk/nextjs'
import { Inter } from "next/font/google"
import { ThemeProvider } from "next-themes"
import { GeistSans } from "geist/font/sans";
import { type Metadata } from "next";
import "~/styles/globals.css"
export const metadata: Metadata = {
title: "Create T3 App",
description: "Generated by create-t3-app",
export const inter = Inter({
subsets: ["latin"],
display: "swap",
variable: "--font-sans",
})
export const metadata = {
title: "T3 App",
description: "Created with create-t3-app",
icons: [{ rel: "icon", url: "/favicon.ico" }],
};
export default function RootLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
return (
<html lang="en" className={`${GeistSans.variable}`}>
<body>{children}</body>
</html>
);
}
export default function RootLayout({ children }: React.PropsWithChildren) {
return (
<ClerkProvider>
{/* <ThemeProvider attribute="class" defaultTheme="system" enableSystem> */}
<html lang="en" className={inter.variable}>
<body className="font-sans">
{children}
</body>
</html>
{/* </ThemeProvider> */}
</ClerkProvider>
)
}

View File

@@ -1,37 +1,74 @@
import Link from "next/link";
import Link from 'next/link';
import Image from 'next/image';
import { auth } from "@clerk/nextjs/server";
import { redirect } from "next/navigation";
export default function HomePage() {
const { userId } = auth();
if (userId) {
redirect("/dash");
}
return (
<main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white">
<div className="container flex flex-col items-center justify-center gap-12 px-4 py-16">
<h1 className="text-5xl font-extrabold tracking-tight text-white sm:text-[5rem]">
Create <span className="text-[hsl(280,100%,70%)]">T3</span> App
</h1>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:gap-8">
<Link
className="flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 text-white hover:bg-white/20"
href="https://create.t3.gg/en/usage/first-steps"
target="_blank"
>
<h3 className="text-2xl font-bold">First Steps </h3>
<div className="text-lg">
Just the basics - Everything you need to know to set up your
database and authentication.
</div>
</Link>
<Link
className="flex max-w-xs flex-col gap-4 rounded-xl bg-white/10 p-4 text-white hover:bg-white/20"
href="https://create.t3.gg/en/introduction"
target="_blank"
>
<h3 className="text-2xl font-bold">Documentation </h3>
<div className="text-lg">
Learn more about Create T3 App, the libraries it uses, and how to
deploy it.
</div>
</Link>
<div className="min-h-screen bg-gradient-to-b from-blue-100 to-white">
<div className="container mx-auto px-4 py-16">
<header className="text-center mb-16">
<h1 className="text-5xl font-bold mb-4 text-blue-800">Welcome to HRIStudio</h1>
<p className="text-xl text-gray-600 max-w-3xl mx-auto">
Empowering Human-Robot Interaction Research and Development
</p>
</header>
<div className="grid md:grid-cols-2 gap-12 items-center mb-16">
<div>
<h2 className="text-3xl font-semibold mb-4 text-blue-700">About HRIStudio</h2>
<p className="text-lg text-gray-700 mb-4">
HRIStudio is a cutting-edge platform designed to streamline the process of creating,
managing, and analyzing Human-Robot Interaction experiments. Our suite of tools
empowers researchers and developers to push the boundaries of HRI research.
</p>
<p className="text-lg text-gray-700 mb-4">
With HRIStudio, you can:
</p>
<ul className="list-disc list-inside text-gray-700 mb-6">
<li>Design complex interaction scenarios with ease</li>
<li>Collect and analyze data in real-time</li>
<li>Collaborate seamlessly with team members</li>
<li>Visualize results with advanced reporting tools</li>
</ul>
</div>
<div className="relative aspect-video w-full">
<Image
src="/hristudio_laptop.png"
alt="HRIStudio Interface on Laptop"
fill
style={{ objectFit: 'contain' }}
// className="rounded-lg shadow-lg"
/>
</div>
</div>
<div className="text-center mb-12">
<h2 className="text-3xl font-semibold mb-4 text-blue-700">Join the HRI Revolution</h2>
<p className="text-lg text-gray-700 mb-6">
Whether you're a seasoned researcher or just starting in the field of Human-Robot Interaction,
HRIStudio provides the tools and support you need to succeed.
</p>
<div className="space-x-4">
<Link href="/sign-in" className="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-6 rounded-full transition duration-300">
Sign In
</Link>
<Link href="/sign-up" className="bg-green-600 hover:bg-green-700 text-white font-bold py-3 px-6 rounded-full transition duration-300">
Sign Up
</Link>
</div>
</div>
<footer className="text-center text-gray-600">
<p>© 2024 HRIStudio. All rights reserved.</p>
</footer>
</div>
</main>
</div>
);
}
}

View File

@@ -0,0 +1,102 @@
"use client"
import { useState } from "react"
import { useSignIn } from "@clerk/nextjs"
import { useRouter } from "next/navigation"
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "~/components/ui/card"
import { Input } from "~/components/ui/input"
import { Button } from "~/components/ui/button"
import { Separator } from "~/components/ui/separator"
import Link from "next/link"
import { FcGoogle } from "react-icons/fc"
import { FaApple } from "react-icons/fa"
export default function SignInPage() {
const { isLoaded, signIn, setActive } = useSignIn()
const [emailAddress, setEmailAddress] = useState("")
const [password, setPassword] = useState("")
const router = useRouter()
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (!isLoaded) return
try {
const result = await signIn.create({
identifier: emailAddress,
password,
})
if (result.status === "complete") {
await setActive({ session: result.createdSessionId })
router.push("/dash")
}
} catch (err: any) {
console.error("Error:", err.errors[0].message)
}
}
const signInWith = (strategy: "oauth_google" | "oauth_apple") => {
if (!isLoaded) return
signIn.authenticateWithRedirect({
strategy,
redirectUrl: "/sso-callback",
redirectUrlComplete: "/dash",
})
}
return (
<div className="min-h-screen bg-gradient-to-b from-blue-100 to-white flex items-center justify-center">
<Card className="w-[350px]">
<CardHeader>
<CardTitle>Sign In to HRIStudio</CardTitle>
<CardDescription>Enter your email and password to sign in</CardDescription>
</CardHeader>
<CardContent>
<div className="grid w-full items-center gap-4">
<Button variant="outline" onClick={() => signInWith("oauth_google")}>
<FcGoogle className="mr-2 h-4 w-4" />
Sign in with Google
</Button>
<Button variant="outline" onClick={() => signInWith("oauth_apple")}>
<FaApple className="mr-2 h-4 w-4" />
Sign in with Apple
</Button>
</div>
<Separator className="my-4" />
<form onSubmit={handleSubmit}>
<div className="grid w-full items-center gap-4">
<div className="flex flex-col space-y-1.5">
<Input
id="email"
placeholder="Email"
type="email"
value={emailAddress}
onChange={(e) => setEmailAddress(e.target.value)}
/>
</div>
<div className="flex flex-col space-y-1.5">
<Input
id="password"
placeholder="Password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<Button className="w-full" type="submit">Sign In</Button>
</div>
</form>
</CardContent>
<CardFooter className="flex flex-col">
<p className="mt-4 text-sm text-center">
Don't have an account?{" "}
<Link href="/sign-up" className="text-blue-600 hover:underline">
Sign up
</Link>
</p>
</CardFooter>
</Card>
</div>
)
}

View File

@@ -0,0 +1,102 @@
"use client"
import { useState } from "react"
import { useSignUp } from "@clerk/nextjs"
import { useRouter } from "next/navigation"
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "~/components/ui/card"
import { Input } from "~/components/ui/input"
import { Button } from "~/components/ui/button"
import { Separator } from "~/components/ui/separator"
import Link from "next/link"
import { FcGoogle } from "react-icons/fc"
import { FaApple } from "react-icons/fa"
export default function SignUpPage() {
const { isLoaded, signUp, setActive } = useSignUp()
const [emailAddress, setEmailAddress] = useState("")
const [password, setPassword] = useState("")
const router = useRouter()
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (!isLoaded) return
try {
const result = await signUp.create({
emailAddress,
password,
})
if (result.status === "complete") {
await setActive({ session: result.createdSessionId })
router.push("/dash")
}
} catch (err: any) {
console.error("Error:", err.errors[0].message)
}
}
const signUpWith = (strategy: "oauth_google" | "oauth_apple") => {
if (!isLoaded) return
signUp.authenticateWithRedirect({
strategy,
redirectUrl: "/sso-callback",
redirectUrlComplete: "/dash",
})
}
return (
<div className="min-h-screen bg-gradient-to-b from-blue-100 to-white flex items-center justify-center">
<Card className="w-[350px]">
<CardHeader>
<CardTitle>Sign Up for HRIStudio</CardTitle>
<CardDescription>Create an account to get started</CardDescription>
</CardHeader>
<CardContent>
<div className="grid w-full items-center gap-4">
<Button variant="outline" onClick={() => signUpWith("oauth_google")}>
<FcGoogle className="mr-2 h-4 w-4" />
Sign up with Google
</Button>
<Button variant="outline" onClick={() => signUpWith("oauth_apple")}>
<FaApple className="mr-2 h-4 w-4" />
Sign up with Apple
</Button>
</div>
<Separator className="my-4" />
<form onSubmit={handleSubmit}>
<div className="grid w-full items-center gap-4">
<div className="flex flex-col space-y-1.5">
<Input
id="email"
placeholder="Email"
type="email"
value={emailAddress}
onChange={(e) => setEmailAddress(e.target.value)}
/>
</div>
<div className="flex flex-col space-y-1.5">
<Input
id="password"
placeholder="Password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<Button className="w-full" type="submit">Sign Up</Button>
</div>
</form>
</CardContent>
<CardFooter className="flex flex-col">
<p className="mt-4 text-sm text-center">
Already have an account?{" "}
<Link href="/sign-in" className="text-blue-600 hover:underline">
Sign in
</Link>
</p>
</CardFooter>
</Card>
</div>
)
}