Extended Dark mode for landing page and user-facing app (#10)

* Extended Dark mode for landing page and user-facing app

* Update LandingPage.tsx

* Fixed issues with dark mode

* Landing Page changes based on comments

* removed migrations

---------

Co-authored-by: vincanger <70215737+vincanger@users.noreply.github.com>
This commit is contained in:
pkyriakou 2023-12-20 19:10:42 +02:00 committed by GitHub
parent b2f8fb481f
commit 3d12c73c02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 91 additions and 67 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
*/.env.client */.env.client
*/.DS_Store */.DS_Store
.DS_Store .DS_Store
*/migrations

View File

@ -43,14 +43,16 @@ export default function App({ children }: { children: ReactNode }) {
return ( return (
<> <>
<div className='min-h-screen dark:text-white dark:bg-boxdark-2'>
{isAdminDashboard ? ( {isAdminDashboard ? (
<>{children}</> <>{children}</>
) : ( ) : (
<> <>
{shouldDisplayAppNavBar && <AppNavBar />} {shouldDisplayAppNavBar && <AppNavBar />}
<div className='mx-auto max-w-7xl sm:px-6 lg:px-8 '>{children}</div> <div className='mx-auto max-w-7xl sm:px-6 lg:px-8'>{children}</div>
</> </>
)} )}
</div>
</> </>
); );
} }

View File

@ -34,20 +34,20 @@ export default function GptPage() {
} = useForm(); } = useForm();
return ( return (
<div className='my-10 lg:mt-20'> <div className='my-10 lg:mt-20 dark:bg-boxdark-2'>
<div className='mx-auto max-w-7xl px-6 lg:px-8'> <div className='mx-auto max-w-7xl px-6 lg:px-8 dark:bg-boxdark'>
<div id='pricing' className='mx-auto max-w-4xl text-center'> <div id='pricing' className='mx-auto max-w-4xl text-center'>
<h2 className='mt-2 text-4xl font-bold tracking-tight text-gray-900 sm:text-5xl'> <h2 className='mt-2 text-4xl font-bold tracking-tight text-gray-900 sm:text-5xl dark:text-white'>
Create your AI-powered <span className='text-yellow-500'>SaaS</span> Create your AI-powered <span className='text-yellow-500'>SaaS</span>
</h2> </h2>
</div> </div>
<p className='mx-auto mt-6 max-w-2xl text-center text-lg leading-8 text-gray-600'> <p className='mx-auto mt-6 max-w-2xl text-center text-lg leading-8 text-gray-600 dark:text-white'>
Below is an example of integrating the OpenAI API into your SaaS. Below is an example of integrating the OpenAI API into your SaaS.
</p> </p>
<form onSubmit={handleSubmit(onSubmit)} className='py-8 mt-10 sm:mt-20 ring-1 ring-gray-200 rounded-lg'> <form onSubmit={handleSubmit(onSubmit)} className='py-8 mt-10 sm:mt-20 ring-1 ring-gray-200 rounded-lg'>
<div className='space-y-6 sm:w-[90%] md:w-[60%] mx-auto border-b border-gray-900/10 px-6 pb-12'> <div className='space-y-6 sm:w-[90%] md:w-[60%] mx-auto border-b border-gray-900/10 px-6 pb-12'>
<div className='col-span-full'> <div className='col-span-full'>
<label htmlFor='instructions' className='block text-sm font-medium leading-6 text-gray-900'> <label htmlFor='instructions' className='block text-sm font-medium leading-6 text-gray-900 dark:text-white'>
Instructions -- How should GPT behave? Instructions -- How should GPT behave?
</label> </label>
<div className='mt-2'> <div className='mt-2'>
@ -71,7 +71,7 @@ export default function GptPage() {
</span> </span>
</div> </div>
<div className='col-span-full'> <div className='col-span-full'>
<label htmlFor='command' className='block text-sm font-medium leading-6 text-gray-900'> <label htmlFor='command' className='block text-sm font-medium leading-6 text-gray-900 dark:text-white'>
Command -- What should GPT do? Command -- What should GPT do?
</label> </label>
<div className='mt-2'> <div className='mt-2'>
@ -95,8 +95,8 @@ export default function GptPage() {
</span> </span>
</div> </div>
<div className='h-10 '> <div className='h-10'>
<label htmlFor='temperature' className='w-full text-gray-700 text-sm font-semibold'> <label htmlFor='temperature' className='w-full text-gray-700 text-sm font-semibold dark:text-white'>
Temperature Input -- Controls How Random GPT's Output is Temperature Input -- Controls How Random GPT's Output is
</label> </label>
<div className='w-32 mt-2'> <div className='w-32 mt-2'>
@ -133,9 +133,9 @@ export default function GptPage() {
<div <div
className={`${ className={`${
isSubmitting && 'animate-pulse' isSubmitting && 'animate-pulse'
} mt-4 mx-6 flex justify-center rounded-lg border border-dashed border-gray-900/25 sm:w-[90%] md:w-[50%] mx-auto mt-12 px-6 py-10`} } mt-4 mx-6 flex justify-center rounded-lg border border-dashed border-gray-900/25 dark:border-white sm:w-[90%] md:w-[50%] mx-auto mt-12 px-6 py-10`}
> >
<div className='space-y-2 flex flex-col gap-2 text-center text-sm text-gray-500 w-full'> <div className='space-y-2 flex flex-col gap-2 text-center text-sm text-gray-500 w-full dark:text-white'>
{response.length > 0 ? response.map((str) => <p key={str}>{str}</p>) : <p>GPT Response will load here</p>} {response.length > 0 ? response.map((str) => <p key={str}>{str}</p>) : <p>GPT Response will load here</p>}
</div> </div>
</div> </div>

View File

@ -57,14 +57,14 @@ const PricingPage = () => {
} }
return ( return (
<div className='my-10 lg:mt-20'> <div className='py-10 lg:mt-10'>
<div className='mx-auto max-w-7xl px-6 lg:px-8'> <div className='mx-auto max-w-7xl px-6 lg:px-8'>
<div id='pricing' className='mx-auto max-w-4xl text-center'> <div id='pricing' className='mx-auto max-w-4xl text-center'>
<h2 className='mt-2 text-4xl font-bold tracking-tight text-gray-900 sm:text-5xl'> <h2 className='mt-2 text-4xl font-bold tracking-tight text-gray-900 sm:text-5xl dark:text-white'>
Pick your <span className='text-yellow-500'>pricing</span> Pick your <span className='text-yellow-500'>pricing</span>
</h2> </h2>
</div> </div>
<p className='mx-auto mt-6 max-w-2xl text-center text-lg leading-8 text-gray-600'> <p className='mx-auto mt-6 max-w-2xl text-center text-lg leading-8 text-gray-600 dark:text-white'>
Stripe subscriptions and secure webhooks are built-in. Just add your Stripe Product IDs! Try it out below with Stripe subscriptions and secure webhooks are built-in. Just add your Stripe Product IDs! Try it out below with
test credit card number{' '} test credit card number{' '}
<span className='px-2 py-1 bg-gray-100 rounded-md text-gray-500'>4242 4242 4242 4242 4242</span> <span className='px-2 py-1 bg-gray-100 rounded-md text-gray-500'>4242 4242 4242 4242 4242</span>
@ -80,7 +80,7 @@ const PricingPage = () => {
{tier.bestDeal && ( {tier.bestDeal && (
<div className='absolute top-0 right-0 -z-10 w-full h-full transform-gpu blur-3xl' aria-hidden='true'> <div className='absolute top-0 right-0 -z-10 w-full h-full transform-gpu blur-3xl' aria-hidden='true'>
<div <div
className='absolute w-full h-full bg-gradient-to-br from-amber-400 to-purple-300 opacity-30' className='absolute w-full h-full bg-gradient-to-br from-amber-400 to-purple-300 opacity-30 dark:opacity-50'
style={{ style={{
clipPath: 'circle(670% at 50% 50%)', clipPath: 'circle(670% at 50% 50%)',
}} }}
@ -89,16 +89,16 @@ const PricingPage = () => {
)} )}
<div className='mb-8'> <div className='mb-8'>
<div className='flex items-center justify-between gap-x-4'> <div className='flex items-center justify-between gap-x-4'>
<h3 id={tier.id} className='text-gray-900 text-lg font-semibold leading-8'> <h3 id={tier.id} className='text-gray-900 text-lg font-semibold leading-8 dark:text-white'>
{tier.name} {tier.name}
</h3> </h3>
</div> </div>
<p className='mt-4 text-sm leading-6 text-gray-600'>{tier.description}</p> <p className='mt-4 text-sm leading-6 text-gray-600 dark:text-white'>{tier.description}</p>
<p className='mt-6 flex items-baseline gap-x-1'> <p className='mt-6 flex items-baseline gap-x-1 dark:text-white'>
<span className='text-4xl font-bold tracking-tight text-gray-900'>{tier.priceMonthly}</span> <span className='text-4xl font-bold tracking-tight text-gray-900 dark:text-white'>{tier.priceMonthly}</span>
<span className='text-sm font-semibold leading-6 text-gray-600'>/month</span> <span className='text-sm font-semibold leading-6 text-gray-600 dark:text-white'>/month</span>
</p> </p>
<ul role='list' className='mt-8 space-y-3 text-sm leading-6 text-gray-600'> <ul role='list' className='mt-8 space-y-3 text-sm leading-6 text-gray-600 dark:text-white'>
{tier.features.map((feature) => ( {tier.features.map((feature) => (
<li key={feature} className='flex gap-x-3'> <li key={feature} className='flex gap-x-3'>
<AiFillCheckCircle className='h-6 w-5 flex-none text-yellow-500' aria-hidden='true' /> <AiFillCheckCircle className='h-6 w-5 flex-none text-yellow-500' aria-hidden='true' />
@ -127,7 +127,7 @@ const PricingPage = () => {
<button <button
onClick={() => handleBuyNowClick(tier.id)} onClick={() => handleBuyNowClick(tier.id)}
aria-describedby={tier.id} aria-describedby={tier.id}
className={` className={`dark:text-white
${tier.id === 'enterprise-tier' ? 'opacity-50 cursor-not-allowed' : 'opacity-100 cursor-pointer'} ${tier.id === 'enterprise-tier' ? 'opacity-50 cursor-not-allowed' : 'opacity-100 cursor-pointer'}
${ ${
tier.bestDeal tier.bestDeal

View File

@ -20,7 +20,7 @@ export default function Login() {
<AuthWrapper> <AuthWrapper>
<LoginForm /> <LoginForm />
<br /> <br />
<span className='text-sm font-medium text-gray-900'> <span className='text-sm font-medium text-gray-900 dark:text-gray-900'>
Don't have an account yet?{' '} Don't have an account yet?{' '}
<Link to='/signup' className='underline'> <Link to='/signup' className='underline'>
go to signup go to signup

View File

@ -2,9 +2,9 @@ import { ReactNode } from 'react';
export function AuthWrapper({children} : {children: ReactNode }) { export function AuthWrapper({children} : {children: ReactNode }) {
return ( return (
<div className='flex min-h-full flex-col justify-center mt-10 sm:px-6 lg:px-8'> <div className='flex min-h-full flex-col justify-center pt-10 sm:px-6 lg:px-8'>
<div className='sm:mx-auto sm:w-full sm:max-w-md'> <div className='sm:mx-auto sm:w-full sm:max-w-md'>
<div className='bg-white py-8 px-4 shadow-xl ring-1 ring-gray-900/10 sm:rounded-lg sm:px-10'> <div className='bg-white py-8 px-4 shadow-xl ring-1 ring-gray-900/10 sm:rounded-lg sm:px-10 dark:bg-white dark:text-gray-900'>
<div className='-mt-8'> <div className='-mt-8'>
{ children } { children }
</div> </div>

View File

@ -5,6 +5,7 @@ import useAuth from '@wasp/auth/useAuth';
import logo from '../static/logo.png'; import logo from '../static/logo.png';
import DropdownUser from './DropdownUser'; import DropdownUser from './DropdownUser';
import { DOCS_URL, BLOG_URL } from '@wasp/shared/constants'; import { DOCS_URL, BLOG_URL } from '@wasp/shared/constants';
import DarkModeSwitcher from '../admin/components/DarkModeSwitcher';
const navigation = [ const navigation = [
{ name: 'GPT Wrapper', href: '/gpt' }, { name: 'GPT Wrapper', href: '/gpt' },
@ -18,7 +19,7 @@ export default function AppNavBar() {
const { data: user, isLoading: isUserLoading } = useAuth(); const { data: user, isLoading: isUserLoading } = useAuth();
return ( return (
<header className='absolute inset-x-0 top-0 z-50 shadow sticky bg-white bg-opacity-50 backdrop-blur-lg backdrop-filter'> <header className='absolute inset-x-0 top-0 z-50 shadow sticky bg-white bg-opacity-50 backdrop-blur-lg backdrop-filter dark:border-strokedark dark:bg-boxdark-2'>
<nav className='flex items-center justify-between p-6 lg:px-8' aria-label='Global'> <nav className='flex items-center justify-between p-6 lg:px-8' aria-label='Global'>
<div className='flex lg:flex-1'> <div className='flex lg:flex-1'>
<a href='/' className='-m-1.5 p-1.5'> <a href='/' className='-m-1.5 p-1.5'>
@ -40,24 +41,32 @@ export default function AppNavBar() {
<a <a
key={item.name} key={item.name}
href={item.href} href={item.href}
className='text-sm font-semibold leading-6 text-gray-900 duration-300 ease-in-out hover:text-yellow-500' className='text-sm font-semibold leading-6 text-gray-900 duration-300 ease-in-out hover:text-yellow-500 dark:text-white'
> >
{item.name} {item.name}
</a> </a>
))} ))}
</div> </div>
<div className='hidden lg:flex lg:flex-1 lg:justify-end lg:align-end'> <div className='hidden lg:flex lg:flex-1 lg:justify-end items-center'>
<div className='flex items-center gap-3 2xsm:gap-7'>
<ul className='flex justify-center items-center gap-2 2xsm:gap-4'>
<DarkModeSwitcher />
</ul>
</div>
{isUserLoading ? null : !user ? ( {isUserLoading ? null : !user ? (
<a href={!user ? '/login' : '/account'} className='text-sm font-semibold leading-6 '> <a href={!user ? '/login' : '/account'} className='text-sm font-semibold leading-6 ml-4'>
<div className='flex justify-end items-center duration-300 ease-in-out text-gray-900 hover:text-yellow-500'> <div className='flex items-center duration-300 ease-in-out text-gray-900 hover:text-yellow-500 dark:text-white'>
Log in <BiLogIn size='1.1rem' className='ml-1 mt-[0.1rem]' /> Log in <BiLogIn size='1.1rem' className='ml-1 mt-[0.1rem]' />
</div> </div>
</a> </a>
) : ( ) : (
<DropdownUser user={user} /> <div className='ml-4'>
<DropdownUser user={user} />
</div>
)} )}
</div> </div>
</nav> </nav>
</header> </header>
); );
} }

View File

@ -43,9 +43,9 @@ const DropdownUser = ({ user } : { user: Partial<User> }) => {
<span className='hidden text-right lg:block'> <span className='hidden text-right lg:block'>
<span className='block text-sm font-medium dark:text-white'>{user.username}</span> <span className='block text-sm font-medium dark:text-white'>{user.username}</span>
</span> </span>
<CgProfile size='1.1rem' className='ml-1 mt-[0.1rem]' /> <CgProfile size='1.1rem' className='ml-1 mt-[0.1rem] dark:text-white' />
<svg <svg
className={`hidden fill-current sm:block ${dropdownOpen ? 'rotate-180' : ''}`} className={`hidden fill-current dark:fill-white sm:block ${dropdownOpen ? 'rotate-180' : ''}`}
width='12' width='12'
height='8' height='8'
viewBox='0 0 12 8' viewBox='0 0 12 8'
@ -64,7 +64,7 @@ const DropdownUser = ({ user } : { user: Partial<User> }) => {
{/* <!-- Dropdown --> */} {/* <!-- Dropdown --> */}
<div <div
ref={dropdown} ref={dropdown}
className={`absolute right-0 mt-4 flex w-62.5 flex-col rounded-sm border border-stroke bg-white shadow-default dark:border-strokedark dark:bg-boxdark ${ className={`absolute right-0 mt-4 flex w-62.5 flex-col rounded-sm border border-stroke bg-white shadow-default dark:border-strokedark dark:bg-boxdark dark:text-white ${
dropdownOpen === true ? 'block' : 'hidden' dropdownOpen === true ? 'block' : 'hidden'
}`} }`}
> >

File diff suppressed because one or more lines are too long