diff --git a/app/api/code/submit/submit-helpers.ts b/app/api/code/submit/submit-helpers.ts
index 7a53569..a651727 100644
--- a/app/api/code/submit/submit-helpers.ts
+++ b/app/api/code/submit/submit-helpers.ts
@@ -7,12 +7,13 @@ const DOMPurify = createDOMPurify(window);
// Sanitizer function
export const validateHTML = (html: string): boolean => {
+ html = html.replace(/\n/g, " ").replace(/\s+/g, " ").trim();
if (!isHtml(html)) {
return false;
}
const cleanHTML = DOMPurify.sanitize(html, {
- ALLOWED_ATTR: ["href", "src", "alt", "title", "style"],
+ ALLOWED_ATTR: ["style", "class"],
FORBID_TAGS: [
"script",
"iframe",
@@ -21,6 +22,8 @@ export const validateHTML = (html: string): boolean => {
"link",
"style",
"form",
+ "img",
+ "a",
],
FORBID_ATTR: [
"onerror",
diff --git a/app/page.tsx b/app/page.tsx
index 6293a4d..a3ac867 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -6,12 +6,12 @@ import AboutTailspin from "@/components/landing/about-tailspin";
import FAQ from "@/components/landing/faq";
import Timeline from "@/components/landing/timeline";
import ThanksPage from "@/components/landing/thanks";
-import StepperCard from "@/components/ui/useCode/StepperCard";
import RatingBody from "@/components/core/rating-area/rating-component";
import GrowOnScroll from "@/components/ui/grow-on-scroll";
import Footer from "@/components/landing/footer";
import ComponentCarousel from "@/components/ui/component-carousel";
import { Separator } from "@/components/ui/separator";
+import ChallengeMain from "@/components/landing/challenge/challenge-main";
export default function Home() {
return (
@@ -41,12 +41,13 @@ export default function Home() {
We hate to be non-inclusive towards phones and
- tablets, however we want to provide you with the
- best experience possible!
+ tablets, however coding on small screens is
+ currently unsupported! Try us on your
+ laptop/desktop!
-
+
@@ -56,11 +57,11 @@ export default function Home() {
, ]}
- title='Some useless information'
+ title='Incase you were wondering...'
/>
-
+
diff --git a/components/core/code-area-actions/submit-button.tsx b/components/core/code-area-actions/submit-button.tsx
index ed0354c..b33e4f0 100644
--- a/components/core/code-area-actions/submit-button.tsx
+++ b/components/core/code-area-actions/submit-button.tsx
@@ -82,8 +82,8 @@ const SubmitButton = () => {
};
const handleContinueButtonClick = () => {
- setContinueClicked(true);
handleReset();
+ setContinueClicked(true);
router.push("/");
};
diff --git a/components/core/rating-area/components/submit-rating-component.tsx b/components/core/rating-area/components/submit-rating-component.tsx
index 16f5250..d87f4a7 100644
--- a/components/core/rating-area/components/submit-rating-component.tsx
+++ b/components/core/rating-area/components/submit-rating-component.tsx
@@ -3,6 +3,7 @@
import { usePutRating } from "@/client-side-queries/rq-queries/rating-submit";
import { Button } from "@/components/ui/button";
import { useRatingStore } from "@/data-store/rating-store";
+import { saveToLocalStorage } from "@/lib/localStorage";
import { Check, Loader2 } from "lucide-react";
import { useEffect, useState } from "react";
import toast from "react-hot-toast";
@@ -28,6 +29,7 @@ const RatingSubmitButton = () => {
if (mutation.isSuccess) {
toast.success("We really appreciated your help!");
setSubmittingRating(false);
+ saveToLocalStorage("rating", "true");
}
}, [mutation.isSuccess]);
diff --git a/components/core/rating-area/rating-component-server.tsx b/components/core/rating-area/rating-component-server.tsx
new file mode 100644
index 0000000..dd2b369
--- /dev/null
+++ b/components/core/rating-area/rating-component-server.tsx
@@ -0,0 +1,57 @@
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
+import OverallRating from "./components/overall-rating";
+import Grid from "./util/arrange-rating-sections";
+import RatingSubmitButton from "./components/submit-rating-component";
+import UxRating from "./components/ux-rating";
+import FunRating from "./components/fun-rating";
+import { FeedbackModal } from "@/components/landing/feedback/feedback-modal";
+
+/*
+Ratings are stored as per the following schema:
+ :
+
+For example:
+- Overall_Rating : 500-100
+ - This states that we currently have a total score of 500 over 100 ratings. Which means, on average, we get 5 stars from every rating.
+- Ux_Rating : 100-30
+ - Implies we have about 3.3333333... stars per rate
+- Fun_Rating : 0-2345
+ - We got 0 stars on average
+*/
+const RatingBodyServer = () => {
+ return (
+
+
+
+ Rate Tailspin
+
+ 30 seconds of your time could translates to a lot of
+ feedback for the team!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default RatingBodyServer;
diff --git a/components/core/rating-area/rating-component.tsx b/components/core/rating-area/rating-component.tsx
index 9ef1a98..bab9776 100644
--- a/components/core/rating-area/rating-component.tsx
+++ b/components/core/rating-area/rating-component.tsx
@@ -1,57 +1,20 @@
-import {
- Card,
- CardContent,
- CardDescription,
- CardFooter,
- CardHeader,
- CardTitle,
-} from "@/components/ui/card";
-import OverallRating from "./components/overall-rating";
-import Grid from "./util/arrange-rating-sections";
-import RatingSubmitButton from "./components/submit-rating-component";
-import UxRating from "./components/ux-rating";
-import FunRating from "./components/fun-rating";
-import { FeedbackModal } from "@/components/landing/feedback/feedback-modal";
+"use client";
-/*
-Ratings are stored as per the following schema:
- :
+import { loadFromLocalStorage } from "@/lib/localStorage";
+import RatingBodyServer from "./rating-component-server";
-For example:
-- Overall_Rating : 500-100
- - This states that we currently have a total score of 500 over 100 ratings. Which means, on average, we get 5 stars from every rating.
-- Ux_Rating : 100-30
- - Implies we have about 3.3333333... stars per rate
-- Fun_Rating : 0-2345
- - We got 0 stars on average
-*/
const RatingBody = () => {
- return (
-
-
-
- Rate Tailspin
-
- 30 seconds of your time could translates to a lot of
- feedback for the team!
-
-
-
-
-
-
-
-
-
-
-
+ It's simple. We'll provide you a coding
+ environment and a target image 🖼️. Your job is to recreate
+ that image using{" "}
+ HTML{" "}
+ and{" "}
+
+ TailwindCSS
+
+ . After you submit, we'll send your scores via Email
+ 📧.
+ Currently, we only provide a playground which
+ represents the core services of Tailspin. When you submit
+ code from our platform, we score your code and email the
+ result of similarity to you.{" "}
+
+ In this MVP, we don't have a way for you to track
+ all your previous submissions or rank yourself against
+ other developers trying out Tailspin.
+
+
+
+
+
+ At this stage, we're presenting a bare bones look at
+ what's to come for Tailspin and looking for{" "}
+
+ feedback
+
+ !
+
+
+
+
+ {button()}
+
+
+ );
+};
+
+export default ChallengeIntro;
diff --git a/components/landing/challenge/challenge-main.tsx b/components/landing/challenge/challenge-main.tsx
new file mode 100644
index 0000000..c089107
--- /dev/null
+++ b/components/landing/challenge/challenge-main.tsx
@@ -0,0 +1,28 @@
+"use client";
+
+import { useState } from "react";
+import ChallengeIntro from "./challenge-intro";
+import StepperCard from "./stepper-pages/StepperCard";
+import { Button } from "@/components/ui/button";
+import { Code } from "lucide-react";
+
+const ChallengeMain = () => {
+ const [goToStepper, setGoToStepper] = useState(false);
+
+ const readyToCodeButton = () => {
+ return (
+
+ );
+ };
+ return (
+ <>
+ {!goToStepper && }
+ {goToStepper && }
+ >
+ );
+};
+
+export default ChallengeMain;
diff --git a/components/ui/enter-code-area-form/Challenge-FormField.tsx b/components/landing/challenge/forms/Challenge-FormField.tsx
similarity index 100%
rename from components/ui/enter-code-area-form/Challenge-FormField.tsx
rename to components/landing/challenge/forms/Challenge-FormField.tsx
diff --git a/components/ui/enter-code-area-form/Email-FormField.tsx b/components/landing/challenge/forms/Email-FormField.tsx
similarity index 100%
rename from components/ui/enter-code-area-form/Email-FormField.tsx
rename to components/landing/challenge/forms/Email-FormField.tsx
diff --git a/components/ui/useCode/Stepper-Form.tsx b/components/landing/challenge/forms/Stepper-Form.tsx
similarity index 82%
rename from components/ui/useCode/Stepper-Form.tsx
rename to components/landing/challenge/forms/Stepper-Form.tsx
index b7f289b..fbddabf 100644
--- a/components/ui/useCode/Stepper-Form.tsx
+++ b/components/landing/challenge/forms/Stepper-Form.tsx
@@ -2,9 +2,9 @@
import { useStepperStore } from "@/data-store/stepper-store";
-import { StepOne } from "./StepOne";
-import { StepTwo } from "./StepTwo";
import { useEffect } from "react";
+import { StepOne } from "../stepper-pages/StepOne";
+import { StepTwo } from "../stepper-pages/StepTwo";
export function StepperForm() {
const { step, setChallenge, setCheck, setEmail, setProgress, setStep } =
diff --git a/components/ui/enter-code-area-form/TOS-FormField.tsx b/components/landing/challenge/forms/TOS-FormField.tsx
similarity index 100%
rename from components/ui/enter-code-area-form/TOS-FormField.tsx
rename to components/landing/challenge/forms/TOS-FormField.tsx
diff --git a/components/ui/enter-code-area-form/StepOne.tsx b/components/landing/challenge/stepper-pages/StepOne.tsx
similarity index 95%
rename from components/ui/enter-code-area-form/StepOne.tsx
rename to components/landing/challenge/stepper-pages/StepOne.tsx
index 52c0b72..f44deea 100644
--- a/components/ui/enter-code-area-form/StepOne.tsx
+++ b/components/landing/challenge/stepper-pages/StepOne.tsx
@@ -7,9 +7,9 @@ import {
useStepperStore,
progressIncrements,
} from "@/data-store/stepper-store";
-import { EmailFormField } from "./Email-FormField";
-import { TOSFormField } from "./TOS-FormField";
import { Loader2 } from "lucide-react";
+import { TOSFormField } from "../forms/TOS-FormField";
+import { EmailFormField } from "../forms/Email-FormField";
export function StepOne() {
const {
diff --git a/components/ui/useCode/StepTwo.tsx b/components/landing/challenge/stepper-pages/StepTwo.tsx
similarity index 97%
rename from components/ui/useCode/StepTwo.tsx
rename to components/landing/challenge/stepper-pages/StepTwo.tsx
index 67cb6e9..ec9a691 100644
--- a/components/ui/useCode/StepTwo.tsx
+++ b/components/landing/challenge/stepper-pages/StepTwo.tsx
@@ -10,10 +10,10 @@ import {
import useSessionStore from "@/data-store/session-store";
import LandingPageCode from "@/components/landing/test-challenges/placeholder-code";
import { useRouter } from "next/navigation";
-import { ChallengeFormField } from "./Challenge-FormField";
import { Loader2 } from "lucide-react";
import { challengeEnum } from "@/data-store/challenge-store";
import { saveToLocalStorage } from "@/lib/localStorage";
+import { ChallengeFormField } from "../forms/Challenge-FormField";
const formStepTwoSchema = z.object({
challenge: z.nativeEnum(challengeEnum, {
diff --git a/components/ui/useCode/StepperCard.tsx b/components/landing/challenge/stepper-pages/StepperCard.tsx
similarity index 59%
rename from components/ui/useCode/StepperCard.tsx
rename to components/landing/challenge/stepper-pages/StepperCard.tsx
index 21086ea..17d00eb 100644
--- a/components/ui/useCode/StepperCard.tsx
+++ b/components/landing/challenge/stepper-pages/StepperCard.tsx
@@ -7,20 +7,22 @@ import {
} from "@/components/ui/card";
import { Progress } from "@/components/ui/progress";
-import { StepperForm } from "./Stepper-Form";
+import { StepperForm } from "../forms/Stepper-Form";
+import { Badge } from "@/components/ui/badge";
export function StepperCard() {
return (
- Try One Of Our Coding Challenges!!!
+
+
Try Out A Coding Challenge!
+ Alpha
+
- {" "}
- Here at TailSpin, we like to have fun! By filling out
- this form, you can use our code editor and attempt to do an
- awesome Tailwind UI challenge!
+ It's simple. Give us an email, accept the TOS, and
+ select a challenge.
diff --git a/components/landing/faq.tsx b/components/landing/faq.tsx
index 2a5996c..9b91697 100644
--- a/components/landing/faq.tsx
+++ b/components/landing/faq.tsx
@@ -15,7 +15,11 @@ const FAQ = () => {
id='accordion'
>
FAQ
-
+
Sounds like an interesting app... What's the catch?
@@ -190,6 +194,61 @@ const FAQ = () => {
+
+
+ When are we implementing accounts?
+
+
+ In this Alpha stage, our plan is to gather feedback from
+ users before we roll out stateful user accounts.
+ We're doing this to test the waters and viability
+ of the concept of Tailspin because developing good
+ quality software takes time and effort. That said, if
+ you haven't given us feedback, you may do so{" "}
+
+ here
+
+ !
+
+
+
+
+ Why do I have to provide my email in the playground?
+
+
+ To make it harder for bad people to spam us and to
+ provide you with a better experience. Tailspin's
+ tech stack includes a managed database, GPT3.5, and
+ serverless compute. We don't want our resources
+ being abused so we insist on an email so that it becomes
+ an extra layer of effort for bad actors to misuse
+ Tailspin. As mentioned, Tailspin uses GPT3.5 and
+ serverless compute. These technologies can take a long
+ time, depending on the total load on these services from
+ other applications. As such, in order to facilitate an
+ asynchronous processing experience, we are essentially
+ running these longer tasks in the background; so we have
+ to send you the results of processing in an asynchronous
+ fashion too - email!
+
+
+
+
+ What was the motivation behind Tailspin?
+
+
+ Wise man once said: "There's no better way to
+ learn than to do." At the time of writing, there
+ isn't a mainstream online TailwindCSS centered
+ platform, where we can write Tailwind powered UI
+ building code and challenge ourselves and one another in
+ the process. Tailspin hopes to close that gap in the
+ community.
+
+
);
diff --git a/components/landing/footer.tsx b/components/landing/footer.tsx
index d7599af..ea5c56d 100644
--- a/components/landing/footer.tsx
+++ b/components/landing/footer.tsx
@@ -1,5 +1,7 @@
import Link from "next/link";
import { TailspinLogo } from "../ui/spinning-logo";
+import { Button } from "../ui/button";
+import { FeedbackModal } from "./feedback/feedback-modal";
const Footer = () => {
return (
@@ -17,27 +19,26 @@ const Footer = () => {
- Building out this landing page. Polishing the
- interactive playground. Adding nice UI/UX.
-
-
V1.0
+
+ Current
+
- Innovate and make incremental improvements to the
- core business of Tailspin - the coding page.
- Iteratively add, optimize, and beautify features to
- the coding page.
+ Bare bones MVP. Users can try the coding challenges
+ and explore Tailspin. We'll work on the
+ feedback we receive from our users and improve our
+ MVP.