Inspiration prompts for home screen (#38)

This commit is contained in:
Will Chen
2025-04-28 22:07:25 -07:00
committed by GitHub
parent 982ba4882f
commit fbb81471da
2 changed files with 396 additions and 83 deletions

View File

@@ -8,11 +8,12 @@ import { useLoadApps } from "@/hooks/useLoadApps";
import { useSettings } from "@/hooks/useSettings";
import { SetupBanner } from "@/components/SetupBanner";
import { isPreviewOpenAtom } from "@/atoms/viewAtoms";
import { useState, useEffect } from "react";
import { useState, useEffect, useCallback } from "react";
import { useStreamChat } from "@/hooks/useStreamChat";
import { HomeChatInput } from "@/components/chat/HomeChatInput";
import { usePostHog } from "posthog-js/react";
import { PrivacyBanner } from "@/components/TelemetryBanner";
import { INSPIRATION_PROMPTS } from "@/prompts/inspiration_prompts";
export default function HomePage() {
const [inputValue, setInputValue] = useAtom(homeChatInputValueAtom);
@@ -28,6 +29,22 @@ export default function HomePage() {
// Get the appId from search params
const appId = search.appId ? Number(search.appId) : null;
// State for random prompts
const [randomPrompts, setRandomPrompts] = useState<
typeof INSPIRATION_PROMPTS
>([]);
// Function to get random prompts
const getRandomPrompts = useCallback(() => {
const shuffled = [...INSPIRATION_PROMPTS].sort(() => 0.5 - Math.random());
return shuffled.slice(0, 5);
}, []);
// Initialize random prompts
useEffect(() => {
setRandomPrompts(getRandomPrompts());
}, [getRandomPrompts]);
// Redirect to app details page if appId is present
useEffect(() => {
if (appId) {
@@ -92,89 +109,59 @@ export default function HomePage() {
<div className="w-full">
<HomeChatInput onSubmit={handleSubmit} />
<div className="flex flex-wrap gap-4 mt-4">
{[
{
icon: (
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"
/>
</svg>
),
label: "TODO list app",
},
{
icon: (
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1h2a1 1 0 001-1v-7m-6 0a1 1 0 00-1 1v3"
/>
</svg>
),
label: "Landing Page",
},
{
icon: (
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
/>
</svg>
),
label: "Sign Up Form",
},
].map((item, index) => (
<button
type="button"
key={index}
onClick={() => setInputValue(`Build me a ${item.label}`)}
className="flex items-center gap-3 px-4 py-2 rounded-xl border border-gray-200
bg-white/50 backdrop-blur-sm
transition-all duration-200
hover:bg-white hover:shadow-md hover:border-gray-300
active:scale-[0.98]
dark:bg-gray-800/50 dark:border-gray-700
dark:hover:bg-gray-800 dark:hover:border-gray-600"
<div className="flex flex-col gap-4 mt-4">
<div className="flex flex-wrap gap-4 justify-center">
{randomPrompts.map((item, index) => (
<button
type="button"
key={index}
onClick={() => setInputValue(`Build me a ${item.label}`)}
className="flex items-center gap-3 px-4 py-2 rounded-xl border border-gray-200
bg-white/50 backdrop-blur-sm
transition-all duration-200
hover:bg-white hover:shadow-md hover:border-gray-300
active:scale-[0.98]
dark:bg-gray-800/50 dark:border-gray-700
dark:hover:bg-gray-800 dark:hover:border-gray-600"
>
<span className="text-gray-700 dark:text-gray-300">
{item.icon}
</span>
<span className="text-sm font-medium text-gray-700 dark:text-gray-300">
{item.label}
</span>
</button>
))}
</div>
<button
type="button"
onClick={() => setRandomPrompts(getRandomPrompts())}
className="self-center flex items-center gap-2 px-4 py-2 rounded-xl border border-gray-200
bg-white/50 backdrop-blur-sm
transition-all duration-200
hover:bg-white hover:shadow-md hover:border-gray-300
active:scale-[0.98]
dark:bg-gray-800/50 dark:border-gray-700
dark:hover:bg-gray-800 dark:hover:border-gray-600"
>
<svg
className="w-5 h-5 text-gray-700 dark:text-gray-300"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<span className="text-gray-700 dark:text-gray-300">
{item.icon}
</span>
<span className="text-sm font-medium text-gray-700 dark:text-gray-300">
{item.label}
</span>
</button>
))}
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
/>
</svg>
<span className="text-sm font-medium text-gray-700 dark:text-gray-300">
More ideas
</span>
</button>
</div>
</div>
<PrivacyBanner />