feat: Add landing page

This commit is contained in:
2024-11-21 00:26:31 -05:00
parent f700cad564
commit 59a9aa67b9
7 changed files with 196 additions and 43 deletions

46
src/app/icon.tsx Normal file
View 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,
}
);
}

View File

@@ -3,9 +3,20 @@ import {
} from '@clerk/nextjs';
import { Inter } from 'next/font/google';
import './globals.css';
import { Metadata } from 'next';
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({
children,
}: {

View File

@@ -1,38 +1,100 @@
'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 { 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() {
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 (
<div className="flex flex-col items-center justify-center min-h-screen p-8">
<h1 className="text-3xl font-bold mb-4">Welcome to HRIStudio</h1>
<SignedOut>
<SignInButton>
<Button>Sign In</Button>
</SignInButton>
</SignedOut>
<SignedIn>
<UserButton />
<p className="mt-4">Signed in as: {user?.emailAddresses[0].emailAddress}</p> {/* Display user's email */}
<SignOutButton>
<Button>Sign Out</Button>
</SignOutButton>
</SignedIn>
<div className="min-h-screen bg-background">
{/* 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>
<SignInButton mode="modal">
<Button variant="ghost">Sign In</Button>
</SignInButton>
<SignInButton mode="modal">
<Button>Sign Up</Button>
</SignInButton>
</SignedOut>
<SignedIn>
<UserButton afterSignOutUrl="/" />
</SignedIn>
</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
View 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>
);
}

View File

@@ -18,6 +18,7 @@ import { useState } from "react"
import { Button } from "~/components/ui/button"
import { Sheet, SheetContent, SheetTrigger, SheetTitle } from "~/components/ui/sheet"
import { cn } from "~/lib/utils"
import { Logo } from "~/components/logo"
const navItems = [
{ name: "Dashboard", href: "/dashboard", icon: LayoutDashboard },
@@ -34,14 +35,6 @@ export function Sidebar() {
const [isOpen, setIsOpen] = useState(false)
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 = () => (
<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">
@@ -86,7 +79,11 @@ export function Sidebar() {
<>
<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">
<HRIStudioLogo />
<Logo
href="/dashboard"
className="text-[hsl(var(--sidebar-foreground))]"
iconClassName="text-[hsl(var(--sidebar-muted))]"
/>
<Sheet open={isOpen} onOpenChange={setIsOpen}>
<SheetTrigger asChild>
<Button variant="ghost" className="h-14 w-14 px-0">
@@ -102,7 +99,11 @@ export function Sidebar() {
</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="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>
<SidebarContent />
</div>