Skip to content

Instantly share code, notes, and snippets.

@Spikeysanju
Created September 17, 2022 06:59
Show Gist options
  • Save Spikeysanju/c0108d48833c3bea5f0d3315e67b8e00 to your computer and use it in GitHub Desktop.
Save Spikeysanju/c0108d48833c3bea5f0d3315e67b8e00 to your computer and use it in GitHub Desktop.
import { Dialog, Transition } from '@headlessui/react';
import {
LinkIcon,
PlusIcon,
QuestionMarkCircleIcon,
XMarkIcon
} from '@heroicons/react/24/solid';
import type { GetServerSideProps, NextPage } from 'next';
import { getSession } from 'next-auth/react';
import Head from 'next/head';
import { Fragment, useState } from 'react';
import ItemFacebookCard from '../components/cards/facebook/ItemFacebookCard';
import ItemInstagramCard from '../components/cards/instagram/ItemInstagramCard';
import ItemLinkedInCard from '../components/cards/linkedin/ItemLinkedInCard';
import ItemTwitterCard from '../components/cards/twitter/ItemTwitterCard';
import ItemYouTubeCard from '../components/cards/youtube/ItemYouTubeCard';
const Home: NextPage = () => {
const [text, setText] = useState<string>('');
const [result, setResult] = useState<string>('');
const [open, setOpen] = useState<boolean>(false);
const team = [
{
name: 'Tom Cook',
email: 'tom.cook@example.com',
href: '#',
imageUrl:
'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80'
},
{
name: 'Whitney Francis',
email: 'whitney.francis@example.com',
href: '#',
imageUrl:
'https://images.unsplash.com/photo-1517365830460-955ce3ccd263?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80'
},
{
name: 'Leonard Krasner',
email: 'leonard.krasner@example.com',
href: '#',
imageUrl:
'https://images.unsplash.com/photo-1519345182560-3f2917c472ef?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80'
},
{
name: 'Floyd Miles',
email: 'floy.dmiles@example.com',
href: '#',
imageUrl:
'https://images.unsplash.com/photo-1463453091185-61582044d556?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80'
},
{
name: 'Emily Selman',
email: 'emily.selman@example.com',
href: '#',
imageUrl:
'https://images.unsplash.com/photo-1502685104226-ee32379fefbe?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80'
}
];
return (
<div>
<Head>
<title>Compose | Abogrow</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="flex w-full items-center justify-center min-h-screen">
<div className=" flex w-full flex-row space-x-4 items-start justify-between min-h-screen ">
{/* Compose field to write the new post */}
<div className="flex flex-1 flex-col bg-white rounded-md sticky top-0 shadow-lg shadow-slate-200 border-r dark:shadow-gray-900 items-start justify-start pb-4 h-fit border border-slate-100 dark:bg-slate-space dark:border-slate-800">
<textarea
id="message"
className="flex-auto w-full h-[500px] text-sm leading-6 text-gray-900 p-8 border-none focus:ring-0 outline-none bg-white dark:bg-slate-space dark:text-white"
placeholder="Your message..."
rows={30}
onChange={(e) => setText(e.target.value)}
value={text}
/>
<div className="flex-auto w-full px-3 mt-9 space-y-3">
<button
className="w-full bg-gradient-to-b rounded-md from-orange-bell-pepper to-red-card text-white font-medium px-4 py-2 shadow-md shadow-red-card/50 dark:shadow-red-card/10"
onClick={() => postToTwitter(text)}
>
Schedule post
</button>
<button
type="button"
className="w-full border border-gray-300 rounded-md bg-white py-2 px-4 font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 dark:bg-slate-800 dark:text-white dark:border-slate-700 dark:hover:bg-slate-space-bg"
onClick={() => setOpen(true)}
>
Save draft
</button>
</div>
</div>
{/* Secondary column (hidden on smaller screens) */}
<aside className="hidden w-96 lg:block lg:sticky lg:top-0 min-h-screen space-y-3">
<div className="space-y-2">
<h1 className=" text-lg font-medium text-gray-900 dark:text-white">
Preview
</h1>
<p className=" text-xs text-gray-500 dark:text-slate-400">
View all previews of your social accounts
</p>
</div>
<div className="flex flex-col space-y-3">
<ItemTwitterCard text={text} />
<ItemLinkedInCard text={text} />
<ItemFacebookCard text={text} />
<ItemInstagramCard text={text} />
<ItemYouTubeCard text={text} />
</div>
</aside>
{/* Share menu to schedule and lable the content */}
<Transition.Root show={open} as={Fragment}>
<Dialog as="div" className="relative z-10" onClose={setOpen}>
<div className="fixed inset-0" />
<div className="fixed inset-0 overflow-hidden">
<div className="absolute inset-0 overflow-hidden">
<div className="pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10 sm:pl-16">
<Transition.Child
as={Fragment}
enter="transform transition ease-in-out duration-500 sm:duration-700"
enterFrom="translate-x-full"
enterTo="translate-x-0"
leave="transform transition ease-in-out duration-500 sm:duration-700"
leaveFrom="translate-x-0"
leaveTo="translate-x-full"
>
<Dialog.Panel className="pointer-events-auto w-screen max-w-2xl">
<form className="flex min-h-screen flex-col overflow-y-scroll bg-white shadow-xl">
<div className="flex-1">
{/* Header */}
<div className="bg-gray-50 px-4 py-6 sm:px-6">
<div className="flex items-start justify-between space-x-3">
<div className="space-y-1">
<Dialog.Title className="text-lg font-medium text-gray-900">
Save draft
</Dialog.Title>
<p className="text-sm text-gray-500">
Get started by filling in the information
below to save your new draft.
</p>
</div>
<div className="flex h-7 items-center">
<button
type="button"
className="text-gray-400 hover:text-gray-500"
onClick={() => setOpen(false)}
>
<span className="sr-only">Close panel</span>
<XMarkIcon
className="h-6 w-6"
aria-hidden="true"
/>
</button>
</div>
</div>
</div>
{/* Divider container */}
<div className="space-y-6 py-6 sm:space-y-0 sm:divide-y sm:divide-gray-200 sm:py-0">
{/* Project name */}
<div className="space-y-1 px-4 sm:grid sm:grid-cols-3 sm:gap-4 sm:space-y-0 sm:px-6 sm:py-5">
<div>
<label
htmlFor="project-name"
className="block text-sm font-medium text-gray-900 sm:mt-px sm:pt-2"
>
Project name
</label>
</div>
<div className="sm:col-span-2">
<input
type="text"
name="project-name"
id="project-name"
autoFocus={true}
className="block w-full h-8 p-2 rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
/>
</div>
</div>
{/* Project description */}
<div className="space-y-1 px-4 sm:grid sm:grid-cols-3 sm:gap-4 sm:space-y-0 sm:px-6 sm:py-5">
<div>
<label
htmlFor="project-description"
className="block text-sm font-medium text-gray-900 sm:mt-px sm:pt-2"
>
Description
</label>
</div>
<div className="sm:col-span-2">
<textarea
id="project-description"
name="project-description"
rows={3}
className="block w-full p-2 rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
defaultValue={''}
/>
</div>
</div>
{/* Team members */}
<div className="space-y-2 px-4 sm:grid sm:grid-cols-3 sm:items-center sm:gap-4 sm:space-y-0 sm:px-6 sm:py-5">
<div>
<h3 className="text-sm font-medium text-gray-900">
Team Members
</h3>
</div>
<div className="sm:col-span-2">
<div className="flex space-x-2">
{team.map((person) => (
<a
key={person.email}
href={person.href}
className="flex-shrink-0 rounded-full hover:opacity-75"
>
<img
className="inline-block h-8 w-8 rounded-full"
src={person.imageUrl}
alt={person.name}
/>
</a>
))}
<button
type="button"
className="inline-flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full border-2 border-dashed border-gray-200 bg-white text-gray-400 hover:border-gray-300 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
>
<span className="sr-only">
Add team member
</span>
<PlusIcon
className="h-5 w-5"
aria-hidden="true"
/>
</button>
</div>
</div>
</div>
{/* Privacy */}
<fieldset className="space-y-2 px-4 sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:space-y-0 sm:px-6 sm:py-5">
<legend className="sr-only">Privacy</legend>
<div
className="text-sm font-medium text-gray-900"
aria-hidden="true"
>
Privacy
</div>
<div className="space-y-5 sm:col-span-2">
<div className="space-y-5 sm:mt-0">
<div className="relative flex items-start">
<div className="absolute flex h-5 items-center">
<input
id="public-access"
name="privacy"
aria-describedby="public-access-description"
type="radio"
className="h-4 w-4 border-gray-300 text-indigo-600 focus:ring-indigo-500"
defaultChecked
/>
</div>
<div className="pl-7 text-sm">
<label
htmlFor="public-access"
className="font-medium text-gray-900"
>
Public access
</label>
<p
id="public-access-description"
className="text-gray-500"
>
Everyone with the link will see this
project
</p>
</div>
</div>
<div className="relative flex items-start">
<div className="absolute flex h-5 items-center">
<input
id="restricted-access"
name="privacy"
aria-describedby="restricted-access-description"
type="radio"
className="h-4 w-4 border-gray-300 text-indigo-600 focus:ring-indigo-500"
/>
</div>
<div className="pl-7 text-sm">
<label
htmlFor="restricted-access"
className="font-medium text-gray-900"
>
Private to Project Members
</label>
<p
id="restricted-access-description"
className="text-gray-500"
>
Only members of this project would be
able to access
</p>
</div>
</div>
<div className="relative flex items-start">
<div className="absolute flex h-5 items-center">
<input
id="private-access"
name="privacy"
aria-describedby="private-access-description"
type="radio"
className="h-4 w-4 border-gray-300 text-indigo-600 focus:ring-indigo-500"
/>
</div>
<div className="pl-7 text-sm">
<label
htmlFor="private-access"
className="font-medium text-gray-900"
>
Private to you
</label>
<p
id="private-access-description"
className="text-gray-500"
>
You are the only one able to access
this project
</p>
</div>
</div>
</div>
<hr className="border-gray-200" />
<div className="space-between sm:space-between flex flex-col space-y-4 sm:flex-row sm:items-center sm:space-y-0">
<div className="flex-1">
<a
href="#"
className="group flex items-center space-x-2.5 text-sm font-medium text-indigo-600 hover:text-indigo-900"
>
<LinkIcon
className="h-5 w-5 text-indigo-500 group-hover:text-indigo-900"
aria-hidden="true"
/>
<span>Copy link</span>
</a>
</div>
<div>
<a
href="#"
className="group flex items-center space-x-2.5 text-sm text-gray-500 hover:text-gray-900"
>
<QuestionMarkCircleIcon
className="h-5 w-5 text-gray-400 group-hover:text-gray-500"
aria-hidden="true"
/>
<span>Learn more about sharing</span>
</a>
</div>
</div>
</div>
</fieldset>
</div>
</div>
{/* Action buttons */}
<div className="flex-shrink-0 border-t border-gray-200 px-4 py-5 sm:px-6">
<div className="flex justify-end space-x-3">
<button
type="button"
className="border rounded-md border-gray-300 bg-white py-2 px-4 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
onClick={() => setOpen(false)}
>
Cancel
</button>
<button
className="inline-flex bg-gradient-to-b rounded-md from-orange-bell-pepper to-red-card text-white font-medium px-4 py-2 shadow-md shadow-red-card/50 dark:shadow-red-card/10"
onClick={() => {
generateText(text);
}}
>
Schedule post
</button>
</div>
</div>
</form>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</div>
</Dialog>
</Transition.Root>
</div>
</main>
</div>
);
async function generateText(prompt: string) {
const response = await fetch(`/api/ai/openai`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt
})
});
const data = await response.json();
setResult(data.response.trim());
}
};
export default Home;
async function postToTwitter(text: string) {
const res = await fetch(`/api/twitter/tweet`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(text)
});
if (!res.ok) {
console.error('Error posting to Twitter');
throw new Error(res.statusText);
}
console.table(res);
return await res.json();
}
export const getServerSideProps: GetServerSideProps = async (context) => {
const session = await getSession(context);
const redirect = {
redirect: {
destination: '/login',
permanent: false
}
};
// Check if the user is authenticated
if (context.res && !session) {
return redirect;
}
return {
props: {}
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment