mirror of
https://github.com/vitalityAI/office.git
synced 2025-04-09 22:10:18 -04:00
new landing page
This commit is contained in:
parent
80be958960
commit
f51b5d2882
|
@ -1,6 +1 @@
|
|||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 36 36" version="1.1" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>pop-out-line</title>
|
||||
<path class="clr-i-outline clr-i-outline-path-1" d="M27,33H5a2,2,0,0,1-2-2V9A2,2,0,0,1,5,7H15V9H5V31H27V21h2V31A2,2,0,0,1,27,33Z"></path><path class="clr-i-outline clr-i-outline-path-2" d="M18,3a1,1,0,0,0,0,2H29.59L15.74,18.85a1,1,0,1,0,1.41,1.41L31,6.41V18a1,1,0,0,0,2,0V3Z"></path>
|
||||
<rect x="0" y="0" width="36" height="36" fill-opacity="0"/>
|
||||
</svg>
|
||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="a-icon--arrow-north-east400 a-icon--text a-icon--no-align top-[0.05em] relative f-ui-1 ml-2 -mr-4" style="width:1em;height:1em;" data-new="" aria-hidden="true" data-v-069f367b=""><polygon fill="currentColor" points="5 4.31 5 5.69 9.33 5.69 2.51 12.51 3.49 13.49 10.31 6.67 10.31 11 11.69 11 11.69 4.31 5 4.31" data-v-069f367b=""></polygon></svg>
|
Before Width: | Height: | Size: 693 B After Width: | Height: | Size: 424 B |
|
@ -87,7 +87,7 @@ const Background = ({className}) => {
|
|||
return (
|
||||
<div className='fixed top-0 left-0 w-full h-full bg-navy z-[-1]'>
|
||||
<Particles
|
||||
className={`w-full h-full ${className} opacity-20`}
|
||||
className={`w-full h-full ${className} opacity-[0.15]`}
|
||||
options={particleParams}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -4,8 +4,8 @@ export const InputField = ({ id, name, value, onChange, className='' }) => {
|
|||
|
||||
return (
|
||||
<div className={`relative w-full mt-6 group ${className}`}>
|
||||
<label className={`pointer-events-none absolute block transition-all ${labelClass} text-white group-focus-within:text-pink`} htmlFor={name}>{name}</label>
|
||||
<input className='w-full pb-2 border-solid border-b-2 border-white text-white bg-transparent transition-all group-focus-within:border-pink' name={id} id={id} value={value} onChange={onChange}></input>
|
||||
<label className={`pointer-events-none absolute block transition-all ${labelClass} text-white group-focus-within:text-blue`} htmlFor={name}>{name}</label>
|
||||
<input className='w-full pb-2 border-solid border-b-2 border-white text-white bg-transparent transition-all group-focus-within:border-blue' name={id} id={id} value={value} onChange={onChange}></input>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -11,8 +11,8 @@ export const Footer = () => {
|
|||
<p>Backend: <a className='inline-block align-middle' href="https://github.com/VitalityAI/therapist">
|
||||
<img className='h-full' src="https://img.shields.io/github/last-commit/VitalityAI/therapist" />
|
||||
</a></p>
|
||||
<p className='ml-4'>Frontend: <a className='inline-block align-middle' href="https://github.com/VitalityAI/therapist">
|
||||
<img className='h-full' src="https://img.shields.io/github/last-commit/VitalityAI/therapist" />
|
||||
<p className='ml-4'>Frontend: <a className='inline-block align-middle' href="https://github.com/VitalityAI/office">
|
||||
<img className='h-full' src="https://img.shields.io/github/last-commit/VitalityAI/office" />
|
||||
</a></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
|
|
@ -25,14 +25,7 @@ export const Layout: FC<any> = ({ dim=false, children }) => {
|
|||
<meta name="theme-color" content="#64A2FF"/>
|
||||
<meta name="background-color" content="#0a192f"/>
|
||||
</Head>
|
||||
<Header/>
|
||||
<div className='relative w-full m-0 h-screen'>
|
||||
<Background className={dim ? "opacity-25" : 'opacity-100'}/>
|
||||
<main className='relative w-full min-h-screen bg-transparent'>
|
||||
{children}
|
||||
<Footer/>
|
||||
</main>
|
||||
</div>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
}
|
171
app/src/pages/demo.tsx
Normal file
171
app/src/pages/demo.tsx
Normal file
|
@ -0,0 +1,171 @@
|
|||
import type { NextPage } from "next";
|
||||
import { Layout } from "@/components/layout";
|
||||
import Image from "next/image";
|
||||
import { useState, useEffect, useLayoutEffect, useRef } from "react";
|
||||
import Header, { notify, ToastType } from "@/components/header";
|
||||
import { Footer } from "@/components/footer";
|
||||
import React from "react";
|
||||
import { handleInputChange } from "@/lib/handleInputChange";
|
||||
import { InputField } from "@/components/InputField";
|
||||
import OutlineButton from "@/components/OutlineButton";
|
||||
import { useToasts } from "@/components/ToastProvider";
|
||||
import { useSession } from 'next-auth/react'
|
||||
import Background from '@/components/Background';
|
||||
|
||||
const Session = ({ data, onClick = () => { }, ...props }) => {
|
||||
return (
|
||||
<div className="relative w-fit bg-white bg-opacity-5 p-6 m-2">
|
||||
<button className={`absolute right-2 top-1 w-fit text-blue transition-all ease-in-out`} onClick={onClick}>{"->"}</button>
|
||||
<p>Caller Phone: {data.callerPhone}</p>
|
||||
<p>Started At: {data.startedAt}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const Demo: NextPage<any> = ({ officers }) => {
|
||||
const { toastDispatch } = useToasts();
|
||||
const [input, setInput] = useState({
|
||||
phone: '',
|
||||
})
|
||||
const [sessions, setSessions] = useState([])
|
||||
const [focusSession, setFocusSession] = useState(null)
|
||||
|
||||
const { data: session } = useSession()
|
||||
const submit = async () => {
|
||||
const operator = await fetch(process.env.NEXT_PUBLIC_API_URL + '/operator/update', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${session['token'].sub}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
phone: input.phone
|
||||
})
|
||||
})
|
||||
|
||||
notify(toastDispatch, "", "Updated Phone: " + input.phone, ToastType.SUCCESS)
|
||||
}
|
||||
|
||||
const popOut = async (session) => {
|
||||
const messages = await (await fetch(process.env.NEXT_PUBLIC_API_URL + '/session/message/?sessionId=' + session.id, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})).json()
|
||||
|
||||
const summary = await (await fetch(process.env.NEXT_PUBLIC_API_URL + '/session/summary/?sessionId=' + session.id, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})).json()
|
||||
|
||||
session.messages = messages.messages;
|
||||
session.summary = summary.summary;
|
||||
console.log(session)
|
||||
|
||||
setFocusSession(session)
|
||||
}
|
||||
|
||||
const transfer = async () => {
|
||||
console.log(session['token'].sub)
|
||||
const res = await (await fetch(process.env.NEXT_PUBLIC_API_URL + '/session/transfer/?sessionId=' + focusSession.id, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${session['token'].sub}`
|
||||
},
|
||||
})).json()
|
||||
await closePop()
|
||||
}
|
||||
|
||||
const closePop = async () => {
|
||||
setFocusSession(null)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(async () => {
|
||||
const fetcher = async () => {
|
||||
const s = await (await fetch(process.env.NEXT_PUBLIC_API_URL + '/session?open=true', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})).json()
|
||||
|
||||
setSessions(s.sessions)
|
||||
}
|
||||
await fetcher()
|
||||
}, 2000)
|
||||
|
||||
return () => clearInterval(interval)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Header />
|
||||
<div className='relative w-full m-0 h-screen'>
|
||||
<Background className="" />
|
||||
<main className='relative w-full min-h-screen bg-transparent'>
|
||||
<div className="relative h-screen py-16 sm:py-24 px-4 sm:px-12 lg:px-24">
|
||||
{
|
||||
session ?
|
||||
<>
|
||||
{focusSession ?
|
||||
<div className="absolute w-fit z-10 text-white bg-black bg-opacity-80 p-8 rounded-sm left-0 right-0 mx-auto">
|
||||
<button className={`absolute right-2 top-1 w-fit text-blue transition-all ease-in-out font-bold`} onClick={closePop}>{"X"}</button>
|
||||
<div className="flex items-center ">
|
||||
<h2 className="w-fit text-3xl font-extrabold">Caller: {focusSession.callerPhone} | {focusSession.startedAt}</h2>
|
||||
<OutlineButton name="Transfer" onClick={transfer} className="ml-8" />
|
||||
</div>
|
||||
<p className="my-4 text-white"><span className="text-blue font-bold">Summary: </span>{focusSession.summary}</p>
|
||||
{focusSession.messages.map(msg => {
|
||||
return (
|
||||
<div key={msg.id}>
|
||||
<p className="text-white"><span className={`${msg.role == "USER" ? "text-green-300" : "text-blue-300"} font-bold`}>{msg.role}: </span>{msg.content}</p>
|
||||
<p></p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
<div className={`${focusSession ? 'blur-sm' : 'blur-0'} transition-all`}>
|
||||
<div className='w-fit bg-white bg-opacity-5 rounded-md p-4 text-center mx-auto'>
|
||||
<h2 className="text-white text-2xl font-extrabold">Hey {session.user.name.split(' ')[0]}!</h2>
|
||||
<p className="text-white text-xl font-light mt-2"> Can you give us your number real quick?</p>
|
||||
|
||||
<div className='w-fit mt-4 mx-auto flex justify-start flex-wrap'>
|
||||
<div className='w-72 mr-4'>
|
||||
<InputField name="Phone Number" id="phone" value={input.phone} onChange={(e) => handleInputChange(e, input, setInput)} className="w-full" />
|
||||
</div>
|
||||
<div className='mt-4 flex items-center justify-center'>
|
||||
<OutlineButton name="Register" onClick={submit} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-16 text-white text-center p-4">
|
||||
<h2 className="text-2xl font-extrabold">Active Calls</h2>
|
||||
<div className="flex justify-center flex-wrap">
|
||||
{sessions.map(session =>
|
||||
<Session data={session} key={session.id} onClick={() => popOut(session)} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</>
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
<Footer />
|
||||
</main>
|
||||
</div>
|
||||
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default Demo;
|
|
@ -12,148 +12,35 @@ import OutlineButton from "@/components/OutlineButton";
|
|||
import { useToasts } from "@/components/ToastProvider";
|
||||
import { useSession } from 'next-auth/react'
|
||||
|
||||
const Session = ({ data, onClick = () => { }, ...props }) => {
|
||||
const PageButton = ({ name = "", link, className = "" }) => {
|
||||
return (
|
||||
<div className="relative w-fit bg-white bg-opacity-5 p-6 m-2">
|
||||
<button className={`absolute right-2 top-1 w-fit text-pink transition-all ease-in-out`} onClick={onClick}>{"->"}</button>
|
||||
<p>Caller Phone: {data.callerPhone}</p>
|
||||
<p>Started At: {data.startedAt}</p>
|
||||
</div>
|
||||
<a href={link} className={`mt-8 group p-2 border-solid border bg-white bg-opacity-0 hover:bg-opacity-5 border-white transition-all ${className}`}>{name} <span className="ml-0 group-hover:ml-1 transition-all">{"->"}</span></a>
|
||||
);
|
||||
}
|
||||
|
||||
const Home: NextPage<any> = ({ officers }) => {
|
||||
const { toastDispatch } = useToasts();
|
||||
const [input, setInput] = useState({
|
||||
phone: '',
|
||||
})
|
||||
const [sessions, setSessions] = useState([])
|
||||
const [focusSession, setFocusSession] = useState(null)
|
||||
|
||||
const { data: session } = useSession()
|
||||
const submit = async () => {
|
||||
const operator = await fetch(process.env.NEXT_PUBLIC_API_URL + '/operator/update', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${session['token'].sub}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
phone: input.phone
|
||||
})
|
||||
})
|
||||
|
||||
notify(toastDispatch, "", "Updated Phone: " + input.phone, ToastType.SUCCESS)
|
||||
}
|
||||
|
||||
const popOut = async (session) => {
|
||||
const messages = await (await fetch(process.env.NEXT_PUBLIC_API_URL + '/session/message/?sessionId=' + session.id, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})).json()
|
||||
|
||||
const summary = await (await fetch(process.env.NEXT_PUBLIC_API_URL + '/session/summary/?sessionId=' + session.id, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
})).json()
|
||||
|
||||
session.messages = messages.messages;
|
||||
session.summary = summary.summary;
|
||||
console.log(session)
|
||||
|
||||
setFocusSession(session)
|
||||
}
|
||||
|
||||
const transfer = async () => {
|
||||
console.log(session['token'].sub)
|
||||
const res = await (await fetch(process.env.NEXT_PUBLIC_API_URL + '/session/transfer/?sessionId=' + focusSession.id, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${session['token'].sub}`
|
||||
},
|
||||
})).json()
|
||||
await closePop()
|
||||
}
|
||||
|
||||
const closePop = async () => {
|
||||
setFocusSession(null)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(async () => {
|
||||
const fetcher = async () => {
|
||||
const s = await (await fetch(process.env.NEXT_PUBLIC_API_URL + '/session?open=true', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})).json()
|
||||
|
||||
setSessions(s.sessions)
|
||||
}
|
||||
await fetcher()
|
||||
}, 2000)
|
||||
|
||||
return () => clearInterval(interval)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className="relative h-screen py-16 sm:py-24 px-4 sm:px-12 lg:px-24">
|
||||
{
|
||||
session ?
|
||||
<>
|
||||
{focusSession ?
|
||||
<div className="absolute w-fit z-10 text-white bg-black bg-opacity-80 p-8 rounded-sm left-0 right-0 mx-auto">
|
||||
<button className={`absolute right-2 top-1 w-fit text-pink transition-all ease-in-out font-bold`} onClick={closePop}>{"X"}</button>
|
||||
<div className="flex items-center ">
|
||||
<h2 className="w-fit text-3xl font-extrabold">Caller: {focusSession.callerPhone} | {focusSession.startedAt}</h2>
|
||||
<OutlineButton name="Transfer" onClick={transfer} className="ml-8" />
|
||||
</div>
|
||||
<p className="my-4 text-white"><span className="text-pink font-bold">Summary: </span>{focusSession.summary}</p>
|
||||
{focusSession.messages.map(msg => {
|
||||
return (
|
||||
<div key={msg.id}>
|
||||
<p className="text-white"><span className={`${msg.role == "USER" ? "text-green-300" : "text-blue-300"} font-bold`}>{msg.role}: </span>{msg.content}</p>
|
||||
<p></p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
: null
|
||||
}
|
||||
<div className={`${focusSession ? 'blur-sm' : 'blur-0'} transition-all`}>
|
||||
<div className='w-fit bg-white bg-opacity-5 rounded-md p-4 text-center mx-auto'>
|
||||
<h2 className="text-white text-2xl font-extrabold">Hey {session.user.name.split(' ')[0]}!</h2>
|
||||
<p className="text-white text-xl font-light mt-2"> Can you give us your number real quick?</p>
|
||||
|
||||
<div className='w-fit mt-4 mx-auto flex justify-start flex-wrap'>
|
||||
<div className='w-72 mr-4'>
|
||||
<InputField name="Phone Number" id="phone" value={input.phone} onChange={(e) => handleInputChange(e, input, setInput)} className="w-full" />
|
||||
</div>
|
||||
<div className='mt-4 flex items-center justify-center'>
|
||||
<OutlineButton name="Register" onClick={submit} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-16 text-white text-center p-4">
|
||||
<h2 className="text-2xl font-extrabold">Active Calls</h2>
|
||||
<div className="flex justify-center flex-wrap">
|
||||
{sessions.map(session =>
|
||||
<Session data={session} key={session.id} onClick={() => popOut(session)} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className='relative w-full m-0 h-screen'>
|
||||
<Background className="" />
|
||||
<main className='relative w-full h-screen bg-transparent text-white '>
|
||||
<div className="flex flex-col justify-center items-center ">
|
||||
<div className="mt-72 max-w-xl">
|
||||
<h1 className="text-6xl font-extrabold">vi·tal·i·ty</h1>
|
||||
<h2 className="text-xl font-light">[vī'talədē] <i>noun</i></h2>
|
||||
<ul className="ml-6 list-decimal">
|
||||
<li>The state of being strong and active; energy. The power giving continuance of life, present in all living things.</li>
|
||||
<li>A next-gen platform connnecting callers in crisis to an AI-powered chatbot for compassionate and responsive support.</li>
|
||||
</ul>
|
||||
<div className="flex ml-6">
|
||||
<PageButton name="Demo" link="/demo" />
|
||||
<PageButton name="Devpost" link="https://devpost.com/software/vitality-q7sbh8" className="ml-4" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</>
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
|
|
|
@ -74,4 +74,20 @@ a {
|
|||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.sphere {
|
||||
position: absolute;
|
||||
top: calc(50% - 150px);
|
||||
left: calc(50% - 150px);
|
||||
height: 300px;
|
||||
width: 300px;
|
||||
border-radius: 50%;
|
||||
box-shadow: inset 0 0 50px #fff,
|
||||
inset 20px 0 80px #f0f,
|
||||
inset -20px 0 80px #0ff,
|
||||
inset 20px 0 300px #f0f,
|
||||
inset -20px 0 300px #0ff,
|
||||
0 0 50px #fff,
|
||||
10px 0 400px #f0f;
|
||||
}
|
Loading…
Reference in New Issue
Block a user