Use Poppins font as default, add snoopForms favicons, update login-screen, add snoopForms colors
* colors, login, UI, fonts * add poppins font * add _document with included favicon and smooth-scrolling * update favicon imports Co-authored-by: knugget <johannes@knugget.de>
@@ -34,7 +34,7 @@ export default function FormList() {
|
||||
<ul className="grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
|
||||
<button onClick={() => newForm()}>
|
||||
<li className="col-span-1">
|
||||
<div className="overflow-hidden text-white bg-red-600 rounded-lg shadow">
|
||||
<div className="overflow-hidden text-white rounded-lg shadow bg-snoopred">
|
||||
<div className="px-4 py-8 sm:p-10">+ New Form</div>
|
||||
</div>
|
||||
</li>
|
||||
@@ -43,7 +43,7 @@ export default function FormList() {
|
||||
.sort((a, b) => b.updatedAt - a.updatedAt)
|
||||
.map((form, formIdx) => (
|
||||
<li key={form.id} className="col-span-1 ">
|
||||
<div className="bg-white divide-y divide-gray-200 rounded-lg shadow">
|
||||
<div className="bg-white divide-y rounded-lg shadow divide-lightgray-200">
|
||||
<Link href={`/forms/${form.id}`}>
|
||||
<a>
|
||||
<div className="px-4 py-5 sm:p-6">{form.name}</div>
|
||||
@@ -54,7 +54,7 @@ export default function FormList() {
|
||||
{({ open }) => (
|
||||
<>
|
||||
<div>
|
||||
<Menu.Button className="flex items-center p-2 -m-2 text-gray-400 rounded-full hover:text-gray-600 focus:outline-none">
|
||||
<Menu.Button className="flex items-center p-2 -m-2 rounded-full text-darkgray-400 hover:text-darkgray-500-600 focus:outline-none">
|
||||
<span className="sr-only">Open options</span>
|
||||
<DotsHorizontalIcon
|
||||
className="w-5 h-5"
|
||||
@@ -84,13 +84,13 @@ export default function FormList() {
|
||||
onClick={() => deleteForm(form, formIdx)}
|
||||
className={classNames(
|
||||
active
|
||||
? "bg-gray-100 text-gray-900"
|
||||
: "text-gray-700",
|
||||
? "bg-lightgray-100 text-darkgray-700"
|
||||
: "text-darkgray-500",
|
||||
"flex px-4 py-2 text-sm w-full"
|
||||
)}
|
||||
>
|
||||
<TrashIcon
|
||||
className="w-5 h-5 mr-3 text-gray-400"
|
||||
className="w-5 h-5 mr-3 text-darkgray-400"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span>Delete Form</span>
|
||||
|
||||
@@ -3,7 +3,7 @@ export default function Loading() {
|
||||
<div className="min-h-screen px-4 py-16 bg-white sm:px-6 sm:py-24 md:grid md:place-items-center lg:px-8">
|
||||
<div className="mx-auto max-w-max">
|
||||
<main className="sm:flex">
|
||||
<p className="mt-1 text-base text-gray-500">Loading...</p>
|
||||
<p className="mt-1 text-base text-darkgray-500">Loading...</p>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,13 +12,13 @@ const formTypes = [
|
||||
id: "NOCODE",
|
||||
title: "No-Code Builder",
|
||||
description:
|
||||
"Use our Notion-like form builder to build your form without a single line of code",
|
||||
"Use our Notion-like form builder to build your form without a single line of code.",
|
||||
},
|
||||
{
|
||||
id: "CODE",
|
||||
title: "Code",
|
||||
description: "Use our snoopReact library to code the form yourself\n",
|
||||
additionalDescription: "(VueJS and other framework support coming soon)",
|
||||
description: "Use our snoopReact library to code the form yourself.",
|
||||
additionalDescription: "",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -73,7 +73,7 @@ export default function FormOnboardingModal({
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<Dialog.Overlay className="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75 backdrop-blur" />
|
||||
<Dialog.Overlay className="fixed inset-0 transition-opacity bg-darkgray-500 bg-opacity-10 backdrop-blur" />
|
||||
</Transition.Child>
|
||||
|
||||
{/* This element is to trick the browser into centering the modal contents. */}
|
||||
@@ -96,33 +96,27 @@ export default function FormOnboardingModal({
|
||||
onSubmit={(e) => submitForm(e)}
|
||||
className="inline-block px-4 pt-5 pb-4 overflow-hidden text-left align-bottom transition-all transform bg-white rounded-lg shadow-xl sm:my-8 sm:align-middle sm:max-w-xl sm:w-full sm:p-6"
|
||||
>
|
||||
<div>
|
||||
<div className="flex items-center justify-center w-12 h-12 mx-auto bg-red-100 rounded-full">
|
||||
{/* <div>
|
||||
<div className="flex items-center justify-center w-12 h-12 mx-auto bg-snoopred-100 rounded-full">
|
||||
<LightBulbIcon
|
||||
className="w-6 h-6 text-red-600"
|
||||
className="w-6 h-6 text-snoopred"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-3 text-center sm:mt-5">
|
||||
<Dialog.Title
|
||||
as="h3"
|
||||
className="text-lg font-medium leading-6 text-gray-900"
|
||||
className="text-lg font-medium leading-6 text-darkgray-700"
|
||||
>
|
||||
Welcome to your form
|
||||
Create a new form
|
||||
</Dialog.Title>
|
||||
<div className="mt-2">
|
||||
<p className="text-sm text-gray-500">
|
||||
Please choose a name and a building approach and then we
|
||||
are ready to start.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr className="my-4" />
|
||||
</div>
|
||||
<hr className="my-4" /> */}
|
||||
<div>
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block text-sm font-medium text-gray-700"
|
||||
className="text-sm text-darkgray-500"
|
||||
>
|
||||
Name your form
|
||||
</label>
|
||||
@@ -130,17 +124,17 @@ export default function FormOnboardingModal({
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
className="block w-full border-gray-300 rounded-md shadow-sm focus:ring-red-500 focus:border-red-500 sm:text-sm"
|
||||
placeholder="My form"
|
||||
className="block w-full p-1 rounded-lg focus:ring-2 focus:ring-snoopred sm:text-lg mb-8"
|
||||
placeholder="e.g. Customer Research Survey"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<hr className="my-5" />
|
||||
{/* <hr className="my-5" /> */}
|
||||
<RadioGroup value={formType} onChange={setFormType}>
|
||||
<RadioGroup.Label className="text-base font-medium text-gray-900">
|
||||
<RadioGroup.Label className="text-sm text-darkgray-500">
|
||||
How would you like to build your form?
|
||||
</RadioGroup.Label>
|
||||
|
||||
@@ -151,8 +145,8 @@ export default function FormOnboardingModal({
|
||||
value={formType}
|
||||
className={({ checked, active }) =>
|
||||
classNames(
|
||||
checked ? "border-transparent" : "border-gray-300",
|
||||
active ? "border-red-500 ring-2 ring-red-500" : "",
|
||||
checked ? "border-transparent" : "border-lightgray-300",
|
||||
active ? "border-snoopred ring-2 ring-snoopred" : "",
|
||||
"relative bg-white border rounded-lg shadow-sm p-4 flex cursor-pointer focus:outline-none"
|
||||
)
|
||||
}
|
||||
@@ -163,19 +157,19 @@ export default function FormOnboardingModal({
|
||||
<span className="flex flex-col">
|
||||
<RadioGroup.Label
|
||||
as="span"
|
||||
className="block text-sm font-medium text-gray-900"
|
||||
className="block text-lg font-medium text-darkgray-900"
|
||||
>
|
||||
{formType.title}
|
||||
</RadioGroup.Label>
|
||||
<RadioGroup.Description
|
||||
as="span"
|
||||
className="flex items-center mt-1 text-sm text-gray-500 whitespace-pre-wrap"
|
||||
className="flex items-center mt-1 text-sm text-darkgray-500 whitespace-pre-wrap"
|
||||
>
|
||||
{formType.description}
|
||||
</RadioGroup.Description>
|
||||
<RadioGroup.Description
|
||||
as="span"
|
||||
className="flex items-center mt-1 text-xs text-gray-400 whitespace-pre-wrap"
|
||||
className="flex items-center mt-1 text-xs text-darkgray-500-400 whitespace-pre-wrap"
|
||||
>
|
||||
{formType.additionalDescription}
|
||||
</RadioGroup.Description>
|
||||
@@ -184,14 +178,14 @@ export default function FormOnboardingModal({
|
||||
<CheckCircleIcon
|
||||
className={classNames(
|
||||
!checked ? "invisible" : "",
|
||||
"h-5 w-5 text-red-600"
|
||||
"h-5 w-5 text-snoopred"
|
||||
)}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span
|
||||
className={classNames(
|
||||
active ? "border" : "border-2",
|
||||
checked ? "border-red-500" : "border-transparent",
|
||||
checked ? "border-snoopred" : "border-transparent",
|
||||
"absolute -inset-px rounded-lg pointer-events-none"
|
||||
)}
|
||||
aria-hidden="true"
|
||||
@@ -205,9 +199,9 @@ export default function FormOnboardingModal({
|
||||
<div className="mt-5 sm:mt-6">
|
||||
<button
|
||||
type="submit"
|
||||
className="inline-flex justify-center w-full px-4 py-2 text-base font-medium text-white bg-red-600 border border-transparent rounded-md shadow-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:text-sm"
|
||||
className="inline-flex justify-center w-full px-4 py-2 text-base font-medium text-white bg-snoopred border border-transparent rounded-md shadow-sm hover:bg-snoopred-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-snoopred sm:text-sm"
|
||||
>
|
||||
Start
|
||||
Create form
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -23,7 +23,7 @@ export default function Layout({ children }) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-100">
|
||||
<div className="min-h-screen bg-lightgray-100">
|
||||
<Disclosure as="nav" className="bg-white shadow-sm">
|
||||
{({ open }) => (
|
||||
<>
|
||||
@@ -31,9 +31,7 @@ export default function Layout({ children }) {
|
||||
<div className="flex justify-between h-16">
|
||||
<div className="flex">
|
||||
<div className="flex items-center flex-shrink-0">
|
||||
<h1 className="font-bold text-red-600 text-md">
|
||||
snoopForms
|
||||
</h1>
|
||||
<img src="../../snoopForms_Logo_v4.svg" alt="snoopForms logo"/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="hidden sm:ml-6 sm:flex sm:items-center">
|
||||
@@ -42,7 +40,7 @@ export default function Layout({ children }) {
|
||||
{({ open }) => (
|
||||
<>
|
||||
<div>
|
||||
<Menu.Button className="flex text-sm bg-white rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500">
|
||||
<Menu.Button className="flex text-sm bg-white rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-snoopred">
|
||||
<span className="sr-only">Open user menu</span>
|
||||
<Image
|
||||
width={32}
|
||||
@@ -72,8 +70,8 @@ export default function Layout({ children }) {
|
||||
<button
|
||||
onClick={() => signOut()}
|
||||
className={classNames(
|
||||
active ? "bg-gray-100" : "",
|
||||
"block px-4 py-2 text-sm text-gray-700 w-full text-left"
|
||||
active ? "bg-lightgray-100" : "",
|
||||
"block px-4 py-2 text-sm text-darkgray-700 hover:text-darkgray-900 w-full text-left"
|
||||
)}
|
||||
>
|
||||
Sign Out
|
||||
@@ -88,7 +86,7 @@ export default function Layout({ children }) {
|
||||
</div>
|
||||
<div className="flex items-center -mr-2 sm:hidden">
|
||||
{/* Mobile menu button */}
|
||||
<Disclosure.Button className="inline-flex items-center justify-center p-2 text-gray-400 bg-white rounded-md hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500">
|
||||
<Disclosure.Button className="inline-flex items-center justify-center p-2 text-darkgray-400 bg-white rounded-md hover:text-darkgray-500 hover:bg-lightgray-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-snoopred">
|
||||
<span className="sr-only">Open main menu</span>
|
||||
{open ? (
|
||||
<XIcon className="block w-6 h-6" aria-hidden="true" />
|
||||
@@ -101,7 +99,7 @@ export default function Layout({ children }) {
|
||||
</div>
|
||||
|
||||
<Disclosure.Panel className="sm:hidden">
|
||||
<div className="pt-4 pb-3 border-t border-gray-200">
|
||||
<div className="pt-4 pb-3 border-t border-lightgray-200">
|
||||
<div className="flex items-center px-4">
|
||||
<div className="flex-shrink-0">
|
||||
<img
|
||||
@@ -114,7 +112,7 @@ export default function Layout({ children }) {
|
||||
<div className="mt-3 space-y-1">
|
||||
<button
|
||||
onClick={() => signOut()}
|
||||
className="block px-4 py-2 text-base font-medium text-gray-500 hover:text-gray-800 hover:bg-gray-100"
|
||||
className="block px-4 py-2 text-base font-medium text-darkgray-500 hover:text-darkgray-800 hover:bg-lightgray-100"
|
||||
>
|
||||
Sign Out
|
||||
</button>
|
||||
|
||||
@@ -22,10 +22,10 @@ export default function LayoutShare({ title, formId, currentStep, children }) {
|
||||
<Head>
|
||||
<title>{title}</title>
|
||||
</Head>
|
||||
<div className="flex min-h-screen overflow-hidden bg-gray-50">
|
||||
<div className="flex min-h-screen overflow-hidden bg-lightgray-50">
|
||||
<div className="flex flex-col flex-1 overflow-hidden">
|
||||
<header className="w-full">
|
||||
<div className="relative z-10 flex flex-shrink-0 h-16 bg-white border-b border-gray-200 shadow-sm">
|
||||
<div className="relative z-10 flex flex-shrink-0 h-16 bg-white border-b border-lightgray-200 shadow-sm">
|
||||
<div className="flex flex-1 px-4 sm:px-6">
|
||||
<MenuBreadcrumbs formId={formId} />
|
||||
<MenuSteps formId={formId} currentStep={currentStep} />
|
||||
|
||||
@@ -21,7 +21,7 @@ export default function MenuBreadcrumbs({ formId }) {
|
||||
<li>
|
||||
<div>
|
||||
<Link href="/forms/">
|
||||
<a className="text-gray-400 hover:text-gray-500">
|
||||
<a className="text-darkgray-400 hover:text-darkgray-500">
|
||||
<HomeIcon
|
||||
className="flex-shrink-0 w-5 h-5"
|
||||
aria-hidden="true"
|
||||
@@ -35,7 +35,7 @@ export default function MenuBreadcrumbs({ formId }) {
|
||||
<li key={page.name}>
|
||||
<div className="flex items-center">
|
||||
<svg
|
||||
className="flex-shrink-0 w-5 h-5 text-gray-300"
|
||||
className="flex-shrink-0 w-5 h-5 text-darkgray-300"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
@@ -45,7 +45,7 @@ export default function MenuBreadcrumbs({ formId }) {
|
||||
</svg>
|
||||
<a
|
||||
href={page.href}
|
||||
className="ml-4 text-sm font-medium text-gray-500 hover:text-gray-700"
|
||||
className="ml-4 text-sm font-medium text-darkgray-500 hover:text-darkgray-500"
|
||||
aria-current={page.current ? "page" : undefined}
|
||||
>
|
||||
{page.name}
|
||||
|
||||
@@ -9,7 +9,7 @@ export default function MenuProfile({}) {
|
||||
{({ open }) => (
|
||||
<>
|
||||
<div>
|
||||
<Menu.Button className="flex text-sm bg-white rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-pink-500">
|
||||
<Menu.Button className="flex text-sm bg-white rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-snoopred-500">
|
||||
<span className="sr-only">Open user menu</span>
|
||||
<img
|
||||
className="w-8 h-8 rounded-full"
|
||||
@@ -37,8 +37,8 @@ export default function MenuProfile({}) {
|
||||
<button
|
||||
onClick={() => signOut()}
|
||||
className={classNames(
|
||||
active ? "bg-gray-100" : "",
|
||||
"block px-4 py-2 text-sm text-gray-700 w-full text-left"
|
||||
active ? "bg-lightgray-100" : "",
|
||||
"block px-4 py-2 text-sm text-darkgray-500 w-full text-left"
|
||||
)}
|
||||
>
|
||||
Sign Out
|
||||
|
||||
@@ -41,7 +41,7 @@ export default function MenuSteps({ formId, currentStep }: MenuStepsProps) {
|
||||
<select
|
||||
id="tabs"
|
||||
name="tabs"
|
||||
className="block w-full py-2 pl-3 pr-10 text-base border-gray-300 rounded-md focus:outline-none focus:ring-red-500 focus:border-red-500 sm:text-sm"
|
||||
className="block w-full py-2 pl-3 pr-10 text-base border-lightgray-300 rounded-md focus:outline-none focus:ring-snoopred focus:border-snoopred sm:text-sm"
|
||||
defaultValue={tabs.find((tab) => tab.id === currentStep).name}
|
||||
onChange={(e) => {
|
||||
const stepId = e.target.children[e.target.selectedIndex].id;
|
||||
@@ -62,8 +62,8 @@ export default function MenuSteps({ formId, currentStep }: MenuStepsProps) {
|
||||
<a
|
||||
className={classNames(
|
||||
tab.id === currentStep
|
||||
? "border-red-500 text-red-600"
|
||||
: "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300",
|
||||
? "border-snoopred text-snoopred"
|
||||
: "border-transparent text-darkgray-500 hover:text-darkgray-500 hover:border-lightgray-300",
|
||||
"whitespace-nowrap py-5 px-1 border-b-2 font-medium text-sm"
|
||||
)}
|
||||
aria-current={tab.id === currentStep ? "page" : undefined}
|
||||
|
||||
74
components/results/Submission.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
import { useMemo } from "react";
|
||||
import { useForm } from "../../lib/forms";
|
||||
import { convertDateTimeString } from "../../lib/utils";
|
||||
import Loading from "../Loading";
|
||||
|
||||
export default function Submission({ formId, submissionSession }) {
|
||||
const { form, isLoadingForm } = useForm(formId);
|
||||
|
||||
// fill the schema with the values provided by the user
|
||||
const getSubmission = (submissionSession, schema) => {
|
||||
if (!schema) return {};
|
||||
const submission = JSON.parse(JSON.stringify(schema));
|
||||
submission.id = submissionSession.id;
|
||||
submission.createdAt = submissionSession.createdAt;
|
||||
if (submissionSession.events.length > 0) {
|
||||
for (const page of submission.pages) {
|
||||
if (page.type === "form") {
|
||||
const pageSubmission = submissionSession.events.find(
|
||||
(s) => s.type === "pageSubmission" && s.data?.pageName === page.name
|
||||
);
|
||||
if (typeof pageSubmission !== "undefined") {
|
||||
for (const element of page.elements) {
|
||||
if (element.type !== "submit") {
|
||||
if (element.name in pageSubmission.data?.submission) {
|
||||
element.value = pageSubmission.data.submission[element.name];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return submission;
|
||||
};
|
||||
|
||||
const submission = useMemo(() => {
|
||||
if (form && submissionSession) {
|
||||
return getSubmission(submissionSession, form.schema);
|
||||
}
|
||||
}, [form, submissionSession]);
|
||||
|
||||
if (isLoadingForm) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-white shadow sm:rounded-lg max-w-">
|
||||
<div className="px-4 py-5 sm:p-6">
|
||||
<div className="text-darkgray-500-600">
|
||||
<p className="text-sm">
|
||||
{convertDateTimeString(submission.createdAt)}
|
||||
</p>
|
||||
{submission.pages.map((page) => (
|
||||
<div key={page.name}>
|
||||
{page.elements?.map(
|
||||
(element) =>
|
||||
element.type !== "submit" && (
|
||||
<div key={element.name}>
|
||||
<p className="font-semibold text-snoopred">
|
||||
{element.label}
|
||||
</p>
|
||||
<p className="font-normal">
|
||||
{element.value || "[not provided]"}
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -21,9 +21,6 @@
|
||||
"nextjs-cors": "^2.1.1",
|
||||
"nodemailer": "^6.7.5",
|
||||
"react": "18.1.0",
|
||||
"react-beautiful-dnd": "^13.1.0",
|
||||
"react-color": "^2.19.3",
|
||||
"react-contenteditable": "^3.3.6",
|
||||
"react-dom": "18.1.0",
|
||||
"react-feather": "^2.0.9",
|
||||
"react-icons": "^4.4.0",
|
||||
|
||||
38
pages/_document.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Html, Head, Main, NextScript } from "next/document";
|
||||
|
||||
export default function Document() {
|
||||
return (
|
||||
<Html className="scroll-smooth">
|
||||
<Head>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="32x32"
|
||||
href="/favicons/favicon-32x32.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="16x16"
|
||||
href="/favicons/favicon-16x16.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="/favicons/apple-touch-icon.png"
|
||||
/>
|
||||
<link rel="manifest" href="/favicons/site.webmanifest" />
|
||||
<link
|
||||
rel="mask-icon"
|
||||
href="/favicons/safari-pinned-tab.svg"
|
||||
color="#5bbad5"
|
||||
/>
|
||||
<meta name="theme-color" content="#0D0010" />
|
||||
</Head>
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
);
|
||||
}
|
||||
@@ -11,22 +11,22 @@ export default function SignIn({ csrfToken }: props) {
|
||||
const router = useRouter();
|
||||
const { error } = router.query;
|
||||
return (
|
||||
<div className="flex min-h-screen bg-white">
|
||||
<div className="flex flex-col justify-center flex-1 px-4 py-12 sm:px-6 lg:flex-none lg:px-20 xl:px-24">
|
||||
<div className="flex min-h-screen bg-lightgray-200">
|
||||
<div className="flex flex-col justify-center flex-1 px-4 py-12 mx-auto sm:px-6 lg:flex-none lg:px-20 xl:px-24">
|
||||
{error && (
|
||||
<div className="absolute p-4 rounded-md top-10 bg-red-50">
|
||||
<div className="absolute p-4 rounded-md top-10 bg-snoopred-50">
|
||||
<div className="flex">
|
||||
<div className="flex-shrink-0">
|
||||
<XCircleIcon
|
||||
className="w-5 h-5 text-red-400"
|
||||
className="w-5 h-5 text-snoopred-400"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
<div className="ml-3">
|
||||
<h3 className="text-sm font-medium text-red-800">
|
||||
<h3 className="text-sm font-medium text-snoopred-800">
|
||||
An error occurred when logging you in
|
||||
</h3>
|
||||
<div className="mt-2 text-sm text-red-700">
|
||||
<div className="mt-2 text-sm text-snoopred-700">
|
||||
<p className="space-y-1 whitespace-pre-wrap">{error}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -34,15 +34,9 @@ export default function SignIn({ csrfToken }: props) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="w-full max-w-sm mx-auto lg:w-96">
|
||||
<div className="w-full bg-white rounded-xl p-8 shadow-cont max-w-sm mx-auto lg:w-96">
|
||||
<div>
|
||||
<h1 className="text-lg font-bold text-red-500">snoopForms</h1>
|
||||
<h2 className="mt-6 text-3xl font-extrabold text-gray-900">
|
||||
Sign in
|
||||
</h2>
|
||||
<p className="mt-2 text-sm text-gray-600">
|
||||
Sign in to your account
|
||||
</p>
|
||||
<img src="../../snoopForms_Logo_v4.svg" alt="snoopForms logo"/>
|
||||
</div>
|
||||
|
||||
<div className="mt-8">
|
||||
@@ -60,7 +54,7 @@ export default function SignIn({ csrfToken }: props) {
|
||||
<div>
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block text-sm font-medium text-gray-700"
|
||||
className="block text-sm font-medium text-darkgray-500"
|
||||
>
|
||||
Email address
|
||||
</label>
|
||||
@@ -71,14 +65,14 @@ export default function SignIn({ csrfToken }: props) {
|
||||
type="email"
|
||||
autoComplete="email"
|
||||
required
|
||||
className="block w-full px-3 py-2 placeholder-gray-400 border border-gray-300 rounded-md shadow-sm appearance-none focus:outline-none focus:ring-pink-500 focus:border-pink-500 sm:text-sm"
|
||||
className="block w-full px-3 py-2 placeholder-lightgray-400 border border-lightgray-300 rounded-md shadow-sm appearance-none focus:outline-none focus:ring-snoopred-500 focus:border-snoopred-500 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label
|
||||
htmlFor="email"
|
||||
className="block text-sm font-medium text-gray-700"
|
||||
className="block text-sm font-medium text-darkgray-500"
|
||||
>
|
||||
Password
|
||||
</label>
|
||||
@@ -89,7 +83,7 @@ export default function SignIn({ csrfToken }: props) {
|
||||
type="password"
|
||||
autoComplete="current-password"
|
||||
required
|
||||
className="block w-full px-3 py-2 placeholder-gray-400 border border-gray-300 rounded-md shadow-sm appearance-none focus:outline-none focus:ring-pink-500 focus:border-pink-500 sm:text-sm"
|
||||
className="block w-full px-3 py-2 placeholder-lightgray-400 border border-lightgray-300 rounded-md shadow-sm appearance-none focus:outline-none focus:ring-snoopred-500 focus:border-snoopred-500 sm:text-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -97,23 +91,18 @@ export default function SignIn({ csrfToken }: props) {
|
||||
<div>
|
||||
<button
|
||||
type="submit"
|
||||
className="flex justify-center w-full px-4 py-2 text-sm font-medium text-white bg-red-600 border border-transparent rounded-md shadow-sm hover:bg-pink-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-pink-500"
|
||||
className="flex justify-center w-full px-4 py-2 text-sm font-medium text-white bg-snoopred border border-transparent rounded-md shadow-sm hover:bg-snoopred-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-snoopred-500"
|
||||
>
|
||||
Sign in
|
||||
</button>
|
||||
<div className="text-center">
|
||||
<a href="" className="text-snoopred hover:text-snoopred-600 text-xs">Create an account</a></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative flex-1 hidden w-0 lg:block">
|
||||
<img
|
||||
className="absolute inset-0 object-cover w-full h-full"
|
||||
src="https://images.unsplash.com/photo-1605362001336-f91645086f32?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1908&q=80"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 15 KiB |
BIN
public/favicons/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
public/favicons/android-chrome-256x256.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
public/favicons/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
public/favicons/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
public/favicons/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
public/favicons/mstile-150x150.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
27
public/favicons/safari-pinned-tab.svg
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="321.000000pt" height="321.000000pt" viewBox="0 0 321.000000 321.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.14, written by Peter Selinger 2001-2017
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,321.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M2765 3003 c-259 -45 -507 -160 -661 -305 -47 -44 -54 -48 -78 -38
|
||||
-31 11 -179 50 -216 56 -14 2 -41 7 -60 10 -57 10 -119 14 -225 15 -109 0
|
||||
-154 -4 -286 -26 -14 -3 -70 -18 -125 -35 -54 -17 -109 -34 -121 -37 -17 -4
|
||||
-39 8 -85 44 -132 104 -325 211 -420 232 -133 30 -227 2 -283 -83 -56 -86 -64
|
||||
-319 -20 -564 20 -112 22 -116 56 -225 l31 -100 -33 -81 c-59 -149 -149 -550
|
||||
-134 -597 5 -16 13 -20 32 -16 19 4 23 1 17 -12 -3 -9 -20 -72 -36 -141 -24
|
||||
-105 -29 -150 -32 -283 -2 -129 0 -161 12 -173 8 -9 21 -13 28 -10 16 6 17 -5
|
||||
4 -59 -33 -130 -32 -415 1 -537 l10 -38 1504 0 1503 0 -3 28 c-2 15 -9 67 -15
|
||||
117 -5 50 -12 101 -14 115 -2 14 -7 46 -10 71 -8 53 -14 94 -21 129 -3 14 -8
|
||||
38 -11 55 -3 16 -12 60 -20 98 -18 86 -18 84 5 63 11 -10 31 -16 48 -14 28 3
|
||||
28 4 27 68 -1 103 -28 281 -68 450 -18 75 -43 162 -72 249 -39 120 -38 115
|
||||
-21 104 21 -13 35 -12 52 6 14 16 14 23 -4 77 -50 155 -99 256 -182 379 l-27
|
||||
40 28 60 c15 33 42 91 60 130 95 205 143 383 144 530 1 129 -20 180 -88 220
|
||||
-45 26 -130 39 -191 28z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
19
public/favicons/site.webmanifest
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "",
|
||||
"short_name": "",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/android-chrome-256x256.png",
|
||||
"sizes": "256x256",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
||||
BIN
public/fonts/Poppins-Black.woff
Normal file
BIN
public/fonts/Poppins-Black.woff2
Normal file
BIN
public/fonts/Poppins-Bold.woff
Normal file
BIN
public/fonts/Poppins-Bold.woff2
Normal file
BIN
public/fonts/Poppins-ExtraBold.woff
Normal file
BIN
public/fonts/Poppins-ExtraBold.woff2
Normal file
BIN
public/fonts/Poppins-ExtraLight.woff
Normal file
BIN
public/fonts/Poppins-ExtraLight.woff2
Normal file
BIN
public/fonts/Poppins-Light.woff
Normal file
BIN
public/fonts/Poppins-Light.woff2
Normal file
BIN
public/fonts/Poppins-Medium.woff
Normal file
BIN
public/fonts/Poppins-Medium.woff2
Normal file
BIN
public/fonts/Poppins-Regular.woff
Normal file
BIN
public/fonts/Poppins-Regular.woff2
Normal file
BIN
public/fonts/Poppins-SemiBold.woff
Normal file
BIN
public/fonts/Poppins-SemiBold.woff2
Normal file
BIN
public/fonts/Poppins-Thin.woff
Normal file
BIN
public/fonts/Poppins-Thin.woff2
Normal file
1
public/snoopForms_Logo_v4.svg
Normal file
|
After Width: | Height: | Size: 35 KiB |
@@ -2,8 +2,83 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
[contenteditable="true"]:empty:before {
|
||||
content: attr(placeholder);
|
||||
display: block;
|
||||
color: #aaa;
|
||||
@font-face {
|
||||
font-family: "Poppins";
|
||||
src: url("/fonts/Poppins-Bold.woff2") format("woff2"),
|
||||
url("/fonts/Poppins-Bold.woff") format("woff");
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Poppins";
|
||||
src: url("/fonts/Poppins-Black.woff2") format("woff2"),
|
||||
url("/fonts/Poppins-Black.woff") format("woff");
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Poppins";
|
||||
src: url("/fonts/Poppins-SemiBold.woff2") format("woff2"),
|
||||
url("/fonts/Poppins-SemiBold.woff") format("woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Poppins";
|
||||
src: url("/fonts/Poppins-ExtraBold.woff2") format("woff2"),
|
||||
url("/fonts/Poppins-ExtraBold.woff") format("woff");
|
||||
font-weight: extrabold;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Poppins";
|
||||
src: url("/fonts/Poppins-Medium.woff2") format("woff2"),
|
||||
url("/fonts/Poppins-Medium.woff") format("woff");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Poppins";
|
||||
src: url("/fonts/Poppins-Light.woff2") format("woff2"),
|
||||
url("/fonts/Poppins-Light.woff") format("woff");
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Poppins";
|
||||
src: url("/fonts/Poppins-Regular.woff2") format("woff2"),
|
||||
url("/fonts/Poppins-Regular.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Poppins";
|
||||
src: url("/fonts/Poppins-Thin.woff2") format("woff2"),
|
||||
url("/fonts/Poppins-Thin.woff") format("woff");
|
||||
font-weight: 100;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Poppins";
|
||||
src: url("/fonts/Poppins-ExtraLight.woff2") format("woff2"),
|
||||
url("/fonts/Poppins-ExtraLight.woff") format("woff");
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,236 @@ module.exports = {
|
||||
"./components/**/*.{js,ts,jsx,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
extend: {
|
||||
colors: {
|
||||
snoopred: {
|
||||
DEFAULT: "#f53b57",
|
||||
50: "#FEECEE",
|
||||
100: "#FDD8DE",
|
||||
200: "#FBB1BC",
|
||||
300: "#F98B9B",
|
||||
400: "#F7647A",
|
||||
500: "#F53B57",
|
||||
600: "#E90C2D",
|
||||
700: "#AF0922",
|
||||
800: "#740617",
|
||||
900: "#3A030B",
|
||||
},
|
||||
lightgreen: {
|
||||
50: "#3dffb3",
|
||||
100: "#33ffa9",
|
||||
200: "#29ff9f",
|
||||
300: "#1ffc95",
|
||||
400: "#15f28b",
|
||||
500: "#0be881",
|
||||
600: "#01de77",
|
||||
700: "#00d46d",
|
||||
800: "#00ca63",
|
||||
900: "#00c059",
|
||||
},
|
||||
darkgreen: {
|
||||
50: "#37f69d",
|
||||
100: "#2dec93",
|
||||
200: "#23e289",
|
||||
300: "#19d87f",
|
||||
400: "#0fce75",
|
||||
500: "#05c46b",
|
||||
600: "#00ba61",
|
||||
700: "#00b057",
|
||||
800: "#00a64d",
|
||||
900: "#009c43",
|
||||
},
|
||||
pink: {
|
||||
50: "#ff89a9",
|
||||
100: "#ff7f9f",
|
||||
200: "#ff7595",
|
||||
300: "#ff6b8b",
|
||||
400: "#f96181",
|
||||
500: "#ef5777",
|
||||
600: "#e54d6d",
|
||||
700: "#db4363",
|
||||
800: "#d13959",
|
||||
900: "#c72f4f",
|
||||
},
|
||||
lightpurple: {
|
||||
50: "#8991ff",
|
||||
100: "#7f87f7",
|
||||
200: "#757ded",
|
||||
300: "#6b73e3",
|
||||
400: "#6169d9",
|
||||
500: "#575fcf",
|
||||
600: "#4d55c5",
|
||||
700: "#434bbb",
|
||||
800: "#3941b1",
|
||||
900: "#2f37a7",
|
||||
},
|
||||
darkpurple: {
|
||||
50: "#6e72f8",
|
||||
100: "#6468ee",
|
||||
200: "#5a5ee4",
|
||||
300: "#5054da",
|
||||
400: "#464ad0",
|
||||
500: "#3c40c6",
|
||||
600: "#3236bc",
|
||||
700: "#282cb2",
|
||||
800: "#1e22a8",
|
||||
900: "#14189e",
|
||||
},
|
||||
lightblue: {
|
||||
50: "#7dffff",
|
||||
100: "#73f7ff",
|
||||
200: "#69edff",
|
||||
300: "#5fe3ff",
|
||||
400: "#55d9ff",
|
||||
500: "#4bcffa",
|
||||
600: "#41c5f0",
|
||||
700: "#37bbe6",
|
||||
800: "#2db1dc",
|
||||
900: "#23a7d2",
|
||||
},
|
||||
darkblue: {
|
||||
50: "#41eeff",
|
||||
100: "#37e4ff",
|
||||
200: "#2ddaff",
|
||||
300: "#23d0ff",
|
||||
400: "#19c6ff",
|
||||
500: "#0fbcf9",
|
||||
600: "#05b2ef",
|
||||
700: "#00a8e5",
|
||||
800: "#009edb",
|
||||
900: "#0094d1",
|
||||
},
|
||||
lightturq: {
|
||||
50: "#66ffff",
|
||||
100: "#5cffff",
|
||||
200: "#52ffff",
|
||||
300: "#48fbf8",
|
||||
400: "#3ef1ee",
|
||||
500: "#34e7e4",
|
||||
600: "#2addda",
|
||||
700: "#20d3d0",
|
||||
800: "#16c9c6",
|
||||
900: "#0cbfbc",
|
||||
},
|
||||
darkturq: {
|
||||
50: "#32ffff",
|
||||
100: "#28fffe",
|
||||
200: "#1ef6f4",
|
||||
300: "#14ecea",
|
||||
400: "#0ae2e0",
|
||||
500: "#00d8d6",
|
||||
600: "#00cecc",
|
||||
700: "#00c4c2",
|
||||
800: "#00bab8",
|
||||
900: "#00b0ae",
|
||||
},
|
||||
lightorange: {
|
||||
50: "#fff27a",
|
||||
100: "#ffe870",
|
||||
200: "#ffde66",
|
||||
300: "#ffd45c",
|
||||
400: "#ffca52",
|
||||
500: "#ffc048",
|
||||
600: "#f5b63e",
|
||||
700: "#ebac34",
|
||||
800: "#e1a22a",
|
||||
900: "#d79820",
|
||||
},
|
||||
darkorange: {
|
||||
50: "#ffda33",
|
||||
100: "#ffd029",
|
||||
200: "#ffc61f",
|
||||
300: "#ffbc15",
|
||||
400: "#ffb20b",
|
||||
500: "#ffa801",
|
||||
600: "#f59e00",
|
||||
700: "#eb9400",
|
||||
800: "#e18a00",
|
||||
900: "#d78000",
|
||||
},
|
||||
lightyellow: {
|
||||
50: "#ffff8b",
|
||||
100: "#ffff81",
|
||||
200: "#fffb77",
|
||||
300: "#fff16d",
|
||||
400: "#ffe763",
|
||||
500: "#ffdd59",
|
||||
600: "#f5d34f",
|
||||
700: "#ebc945",
|
||||
800: "#e1bf3b",
|
||||
900: "#d7b531",
|
||||
},
|
||||
darkyellow: {
|
||||
50: "#ffff5c",
|
||||
100: "#fffb52",
|
||||
200: "#fff148",
|
||||
300: "#ffe73e",
|
||||
400: "#ffdd34",
|
||||
500: "#ffd32a",
|
||||
600: "#f5c920",
|
||||
700: "#ebbf16",
|
||||
800: "#e1b50c",
|
||||
900: "#d7ab02",
|
||||
},
|
||||
lightgray: {
|
||||
50: "#ffffff",
|
||||
100: "#faffff",
|
||||
200: "#f0f8ff",
|
||||
300: "#e6eef6",
|
||||
400: "#dce4ec",
|
||||
500: "#d2dae2",
|
||||
600: "#c8d0d8",
|
||||
700: "#bec6ce",
|
||||
800: "#b4bcc4",
|
||||
900: "#aab2ba",
|
||||
},
|
||||
darkgray: {
|
||||
50: "#b2c0cd",
|
||||
100: "#a8b6c3",
|
||||
200: "#9eacb9",
|
||||
300: "#94a2af",
|
||||
400: "#8a98a5",
|
||||
500: "#808e9b",
|
||||
600: "#768491",
|
||||
700: "#6c7a87",
|
||||
800: "#62707d",
|
||||
900: "#586673",
|
||||
},
|
||||
lightblack: {
|
||||
50: "#7a8692",
|
||||
100: "#707c88",
|
||||
200: "#66727e",
|
||||
300: "#5c6874",
|
||||
400: "#525e6a",
|
||||
500: "#485460",
|
||||
600: "#3e4a56",
|
||||
700: "#34404c",
|
||||
800: "#2a3642",
|
||||
900: "#202c38",
|
||||
},
|
||||
darkblack: {
|
||||
50: "#505960",
|
||||
100: "#464f56",
|
||||
200: "#3c454c",
|
||||
300: "#323b42",
|
||||
400: "#283138",
|
||||
500: "#1e272e",
|
||||
600: "#141d24",
|
||||
700: "#0a131a",
|
||||
800: "#000910",
|
||||
900: "#000006",
|
||||
},
|
||||
},
|
||||
dropShadow: {
|
||||
cont: "7.5px 7.5px 13.7px 4.5px rgba(0, 0, 0, 0.2);",
|
||||
},
|
||||
fontFamily: {
|
||||
sans: "Poppins, Arial, sans-serif",
|
||||
},
|
||||
// fontFamily: {
|
||||
// sans: "Arial, Poppins, Montserrat, Roboto, system ui, sans-serif, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',, 'Helvetica Neue', Arial",
|
||||
// },
|
||||
},
|
||||
},
|
||||
plugins: [require("@tailwindcss/forms"), require("@tailwindcss/typography")],
|
||||
};
|
||||
|
||||