mirror of
https://github.com/soconnor0919/hristudio.git
synced 2025-12-11 22:54:45 -05:00
feat: Add landing page
This commit is contained in:
3
.env
3
.env
@@ -1,3 +0,0 @@
|
|||||||
POSTGRES_URL=""
|
|
||||||
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_ZmFjdHVhbC1saWdlci0xMi5jbGVyay5hY2NvdW50cy5kZXYk
|
|
||||||
CLERK_SECRET_KEY=sk_test_67aglhtMoQwtdV5sRzkpCDE4F8S2nWyyGVW5XQAJ6o
|
|
||||||
BIN
public/hristudio_laptop.png
Normal file
BIN
public/hristudio_laptop.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 MiB |
46
src/app/icon.tsx
Normal file
46
src/app/icon.tsx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { ImageResponse } from "next/og";
|
||||||
|
|
||||||
|
export const runtime = "edge";
|
||||||
|
export const contentType = "image/svg+xml";
|
||||||
|
export const size = {
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Icon() {
|
||||||
|
return new ImageResponse(
|
||||||
|
(
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
background: "transparent",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M12 8V4H8" />
|
||||||
|
<rect width="16" height="12" x="4" y="8" rx="2" />
|
||||||
|
<path d="M2 14h2" />
|
||||||
|
<path d="M20 14h2" />
|
||||||
|
<path d="M15 13v2" />
|
||||||
|
<path d="M9 13v2" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
{
|
||||||
|
...size,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -3,9 +3,20 @@ import {
|
|||||||
} from '@clerk/nextjs';
|
} from '@clerk/nextjs';
|
||||||
import { Inter } from 'next/font/google';
|
import { Inter } from 'next/font/google';
|
||||||
import './globals.css';
|
import './globals.css';
|
||||||
|
import { Metadata } from 'next';
|
||||||
|
|
||||||
const inter = Inter({ subsets: ['latin'] });
|
const inter = Inter({ subsets: ['latin'] });
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'HRIStudio',
|
||||||
|
description: 'A platform for managing human-robot interaction studies',
|
||||||
|
icons: {
|
||||||
|
icon: [
|
||||||
|
{ url: '/icon', type: 'image/svg+xml' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
|
|||||||
110
src/app/page.tsx
110
src/app/page.tsx
@@ -1,38 +1,100 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { SignedIn, SignedOut, SignInButton, SignOutButton, UserButton, useUser } from "@clerk/nextjs";
|
import { SignedIn, SignedOut, SignInButton, SignOutButton, UserButton } from "@clerk/nextjs";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import { useEffect, useState } from "react";
|
import Image from "next/image";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { BotIcon } from "lucide-react";
|
||||||
|
import { Logo } from "~/components/logo";
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const { user, isLoaded } = useUser(); // Get user information and loading state
|
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isLoaded) {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
}, [isLoaded]);
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return <div>Loading...</div>; // Show a loading state while fetching user data
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center justify-center min-h-screen p-8">
|
<div className="min-h-screen bg-background">
|
||||||
<h1 className="text-3xl font-bold mb-4">Welcome to HRIStudio</h1>
|
{/* Navigation Bar */}
|
||||||
|
<nav className="border-b bg-card/50 backdrop-blur supports-[backdrop-filter]:bg-card/50">
|
||||||
|
<div className="container mx-auto px-4 h-16 flex items-center justify-between">
|
||||||
|
<Logo />
|
||||||
|
<div className="flex items-center space-x-4">
|
||||||
<SignedOut>
|
<SignedOut>
|
||||||
<SignInButton>
|
<SignInButton mode="modal">
|
||||||
<Button>Sign In</Button>
|
<Button variant="ghost">Sign In</Button>
|
||||||
|
</SignInButton>
|
||||||
|
<SignInButton mode="modal">
|
||||||
|
<Button>Sign Up</Button>
|
||||||
</SignInButton>
|
</SignInButton>
|
||||||
</SignedOut>
|
</SignedOut>
|
||||||
<SignedIn>
|
<SignedIn>
|
||||||
<UserButton />
|
<UserButton afterSignOutUrl="/" />
|
||||||
<p className="mt-4">Signed in as: {user?.emailAddresses[0].emailAddress}</p> {/* Display user's email */}
|
|
||||||
<SignOutButton>
|
|
||||||
<Button>Sign Out</Button>
|
|
||||||
</SignOutButton>
|
|
||||||
</SignedIn>
|
</SignedIn>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{/* Hero Section */}
|
||||||
|
<section className="container mx-auto px-4 py-24 grid lg:grid-cols-2 gap-12 items-center">
|
||||||
|
<div>
|
||||||
|
<h1 className="text-4xl font-bold tracking-tight lg:text-6xl">
|
||||||
|
Streamline Your HRI Research
|
||||||
|
</h1>
|
||||||
|
<p className="mt-6 text-xl text-muted-foreground">
|
||||||
|
A comprehensive platform for designing, executing, and analyzing Wizard-of-Oz experiments in human-robot interaction studies.
|
||||||
|
</p>
|
||||||
|
<div className="mt-8 flex flex-col sm:flex-row gap-4">
|
||||||
|
<SignedOut>
|
||||||
|
<SignInButton mode="modal">
|
||||||
|
<Button size="lg" className="w-full sm:w-auto">
|
||||||
|
Get Started
|
||||||
|
</Button>
|
||||||
|
</SignInButton>
|
||||||
|
</SignedOut>
|
||||||
|
<SignedIn>
|
||||||
|
<Button size="lg" className="w-full sm:w-auto" asChild>
|
||||||
|
<Link href="/dashboard">
|
||||||
|
Go to Dashboard
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
</SignedIn>
|
||||||
|
<Button size="lg" variant="outline" className="w-full sm:w-auto" asChild>
|
||||||
|
<Link href="https://github.com/soconnor0919/hristudio" target="_blank">
|
||||||
|
View on GitHub
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="relative">
|
||||||
|
<Image
|
||||||
|
src="/hristudio_laptop.png"
|
||||||
|
alt="HRIStudio Interface"
|
||||||
|
width={800}
|
||||||
|
height={600}
|
||||||
|
priority
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Features Section */}
|
||||||
|
<section className="container mx-auto px-4 py-24">
|
||||||
|
<div className="grid md:grid-cols-3 gap-8">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="text-xl font-semibold">Visual Experiment Design</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Create and configure experiments using an intuitive drag-and-drop interface without extensive coding.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="text-xl font-semibold">Real-time Control</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Execute experiments with synchronized views for wizards and observers, enabling seamless collaboration.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="text-xl font-semibold">Comprehensive Analysis</h3>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
Record, playback, and analyze experimental data with built-in annotation and export tools.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
36
src/components/logo.tsx
Normal file
36
src/components/logo.tsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { BotIcon } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { cn } from "~/lib/utils";
|
||||||
|
|
||||||
|
interface LogoProps {
|
||||||
|
href?: string;
|
||||||
|
className?: string;
|
||||||
|
iconClassName?: string;
|
||||||
|
textClassName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Logo({
|
||||||
|
href = "/",
|
||||||
|
className,
|
||||||
|
iconClassName,
|
||||||
|
textClassName
|
||||||
|
}: LogoProps) {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
href={href}
|
||||||
|
className={cn(
|
||||||
|
"flex items-center font-sans text-xl",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<BotIcon className={cn(
|
||||||
|
"h-6 w-6 mr-1 text-muted-foreground",
|
||||||
|
iconClassName
|
||||||
|
)} />
|
||||||
|
<span className={cn(textClassName)}>
|
||||||
|
<span className="font-extrabold">HRI</span>
|
||||||
|
<span className="font-normal">Studio</span>
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ import { useState } from "react"
|
|||||||
import { Button } from "~/components/ui/button"
|
import { Button } from "~/components/ui/button"
|
||||||
import { Sheet, SheetContent, SheetTrigger, SheetTitle } from "~/components/ui/sheet"
|
import { Sheet, SheetContent, SheetTrigger, SheetTitle } from "~/components/ui/sheet"
|
||||||
import { cn } from "~/lib/utils"
|
import { cn } from "~/lib/utils"
|
||||||
|
import { Logo } from "~/components/logo"
|
||||||
|
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{ name: "Dashboard", href: "/dashboard", icon: LayoutDashboard },
|
{ name: "Dashboard", href: "/dashboard", icon: LayoutDashboard },
|
||||||
@@ -34,14 +35,6 @@ export function Sidebar() {
|
|||||||
const [isOpen, setIsOpen] = useState(false)
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
const { user } = useUser()
|
const { user } = useUser()
|
||||||
|
|
||||||
const HRIStudioLogo = () => (
|
|
||||||
<Link href="/dashboard" className="flex items-center font-sans text-xl text-[hsl(var(--sidebar-foreground))]">
|
|
||||||
<BotIcon className="h-6 w-6 mr-1 text-[hsl(var(--sidebar-muted))]" />
|
|
||||||
<span className="font-extrabold">HRI</span>
|
|
||||||
<span className="font-normal">Studio</span>
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
|
|
||||||
const SidebarContent = () => (
|
const SidebarContent = () => (
|
||||||
<div className="flex h-full flex-col bg-gradient-to-b from-[hsl(var(--sidebar-background-top))] to-[hsl(var(--sidebar-background-bottom))]">
|
<div className="flex h-full flex-col bg-gradient-to-b from-[hsl(var(--sidebar-background-top))] to-[hsl(var(--sidebar-background-bottom))]">
|
||||||
<nav className="flex-1 overflow-y-auto p-4">
|
<nav className="flex-1 overflow-y-auto p-4">
|
||||||
@@ -86,7 +79,11 @@ export function Sidebar() {
|
|||||||
<>
|
<>
|
||||||
<div className="lg:hidden fixed top-0 left-0 right-0 z-50">
|
<div className="lg:hidden fixed top-0 left-0 right-0 z-50">
|
||||||
<div className="flex h-14 items-center justify-between border-b px-4 bg-background">
|
<div className="flex h-14 items-center justify-between border-b px-4 bg-background">
|
||||||
<HRIStudioLogo />
|
<Logo
|
||||||
|
href="/dashboard"
|
||||||
|
className="text-[hsl(var(--sidebar-foreground))]"
|
||||||
|
iconClassName="text-[hsl(var(--sidebar-muted))]"
|
||||||
|
/>
|
||||||
<Sheet open={isOpen} onOpenChange={setIsOpen}>
|
<Sheet open={isOpen} onOpenChange={setIsOpen}>
|
||||||
<SheetTrigger asChild>
|
<SheetTrigger asChild>
|
||||||
<Button variant="ghost" className="h-14 w-14 px-0">
|
<Button variant="ghost" className="h-14 w-14 px-0">
|
||||||
@@ -102,7 +99,11 @@ export function Sidebar() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="hidden lg:flex lg:w-64 lg:flex-col lg:border-r lg:bg-gradient-to-b lg:from-[hsl(var(--sidebar-background-top))] lg:to-[hsl(var(--sidebar-background-bottom))]">
|
<div className="hidden lg:flex lg:w-64 lg:flex-col lg:border-r lg:bg-gradient-to-b lg:from-[hsl(var(--sidebar-background-top))] lg:to-[hsl(var(--sidebar-background-bottom))]">
|
||||||
<div className="flex h-14 items-center border-b px-4">
|
<div className="flex h-14 items-center border-b px-4">
|
||||||
<HRIStudioLogo />
|
<Logo
|
||||||
|
href="/dashboard"
|
||||||
|
className="text-[hsl(var(--sidebar-foreground))]"
|
||||||
|
iconClassName="text-[hsl(var(--sidebar-muted))]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<SidebarContent />
|
<SidebarContent />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user