mirror of
https://github.com/FranP-code/create-better-t-stack.git
synced 2025-10-12 23:52:15 +00:00
refactor(web): replace preloadQuery with fetchQuery
This commit is contained in:
@@ -1,5 +1,12 @@
|
||||
"use client";
|
||||
import { Check, ChevronDown, ChevronRight, Copy, Terminal } from "lucide-react";
|
||||
import {
|
||||
Check,
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
Copy,
|
||||
Terminal,
|
||||
Zap,
|
||||
} from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
import {
|
||||
@@ -28,7 +35,7 @@ export default function CommandSection() {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mb-8 grid grid-cols-1 gap-4 lg:grid-cols-2">
|
||||
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
|
||||
<div className="flex h-full flex-col justify-between rounded border border-border p-4">
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -104,7 +111,7 @@ export default function CommandSection() {
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between rounded border border-border p-3">
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
<span className="text-primary">⚡</span>
|
||||
<Zap className="h-4 w-4 text-primary" />
|
||||
<span className="text-foreground">
|
||||
Interactive configuration wizard
|
||||
</span>
|
||||
|
||||
@@ -2,7 +2,7 @@ import NpmPackage from "./npm-package";
|
||||
|
||||
export default function HeroSection() {
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<div className="mb-8 flex items-center justify-center">
|
||||
<div className="flex flex-wrap items-center justify-center gap-2 sm:gap-4 md:gap-6">
|
||||
<pre className="ascii-art text-primary text-xs leading-tight sm:text-sm">
|
||||
@@ -47,15 +47,12 @@ export default function HeroSection() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-6 text-center">
|
||||
<div className="text-center">
|
||||
<p className="mx-auto text-lg text-muted-foreground">
|
||||
Modern CLI for scaffolding end-to-end type-safe TypeScript projects
|
||||
</p>
|
||||
<p className="mx-auto mt-2 max-w-2xl text-muted-foreground text-sm">
|
||||
Production-ready • Customizable • Best practices included
|
||||
</p>
|
||||
<NpmPackage />
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
"use client";
|
||||
import type { api } from "@better-t-stack/backend/convex/_generated/api";
|
||||
import { type Preloaded, usePreloadedQuery } from "convex/react";
|
||||
import {
|
||||
ChevronDown,
|
||||
ChevronUp,
|
||||
@@ -26,17 +24,33 @@ import {
|
||||
sortSponsors,
|
||||
} from "@/lib/sponsor-utils";
|
||||
|
||||
export default function SponsorsSection({
|
||||
preloadedSponsors,
|
||||
}: {
|
||||
preloadedSponsors: Preloaded<typeof api.sponsors.getSponsors>;
|
||||
}) {
|
||||
const sponsorsData = usePreloadedQuery(preloadedSponsors);
|
||||
type SponsorEntry = {
|
||||
sponsor: {
|
||||
login: string;
|
||||
name: string;
|
||||
avatarUrl: string;
|
||||
websiteUrl?: string;
|
||||
linkUrl: string;
|
||||
customLogoUrl?: string;
|
||||
type: string;
|
||||
};
|
||||
isOneTime: boolean;
|
||||
monthlyDollars: number;
|
||||
privacyLevel: string;
|
||||
tierName: string;
|
||||
createdAt: string;
|
||||
provider: string;
|
||||
};
|
||||
|
||||
export default function SponsorsSection({
|
||||
sponsors,
|
||||
}: {
|
||||
sponsors: Array<SponsorEntry>;
|
||||
}) {
|
||||
const [showPastSponsors, setShowPastSponsors] = useState(false);
|
||||
|
||||
const sponsors =
|
||||
sponsorsData.map((sponsor) => ({
|
||||
const sponsorsData =
|
||||
sponsors.map((sponsor) => ({
|
||||
...sponsor,
|
||||
sponsor: {
|
||||
...sponsor.sponsor,
|
||||
@@ -44,16 +58,16 @@ export default function SponsorsSection({
|
||||
},
|
||||
})) || [];
|
||||
|
||||
const visibleSponsors = filterVisibleSponsors(sponsors);
|
||||
const visibleSponsors = filterVisibleSponsors(sponsorsData);
|
||||
const sortedSponsors = sortSponsors(visibleSponsors);
|
||||
const currentSponsors = filterCurrentSponsors(sortedSponsors);
|
||||
const pastSponsors = filterPastSponsors(sortSponsors(sponsors));
|
||||
const pastSponsors = filterPastSponsors(sortSponsors(sponsorsData));
|
||||
const specialSponsors = sortSpecialSponsors(
|
||||
filterSpecialSponsors(currentSponsors),
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="mb-12">
|
||||
<div className="">
|
||||
<div className="mb-6 flex flex-wrap items-center justify-between gap-2 sm:flex-nowrap">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal className="h-5 w-5 text-primary" />
|
||||
|
||||
@@ -33,7 +33,7 @@ export default function StatsSection({
|
||||
const liveNpmDownloadCount = useNpmDownloadCounter(npmPackages);
|
||||
|
||||
return (
|
||||
<div className="mb-8 grid grid-cols-1 gap-4 sm:mb-12 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<Link href="/analytics">
|
||||
<div className="cursor-pointer rounded border border-border p-4 transition-colors hover:bg-muted/10">
|
||||
<div className="mb-3 flex items-center gap-2">
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import type { api } from "@better-t-stack/backend/convex/_generated/api";
|
||||
import { type Preloaded, usePreloadedQuery } from "convex/react";
|
||||
import { Play, Terminal } from "lucide-react";
|
||||
import { motion } from "motion/react";
|
||||
import Image from "next/image";
|
||||
@@ -99,14 +97,13 @@ const TweetCard = ({ tweetId, index }: { tweetId: string; index: number }) => (
|
||||
);
|
||||
|
||||
export default function Testimonials({
|
||||
preloadedTestimonialsTweet,
|
||||
preloadedTestimonialsVideos,
|
||||
videos,
|
||||
tweets,
|
||||
}: {
|
||||
preloadedTestimonialsTweet: Preloaded<typeof api.testimonials.getTweets>;
|
||||
preloadedTestimonialsVideos: Preloaded<typeof api.testimonials.getVideos>;
|
||||
videos: Array<{ embedId: string; title: string }>;
|
||||
tweets: Array<{ tweetId: string }>;
|
||||
}) {
|
||||
const videos = usePreloadedQuery(preloadedTestimonialsVideos).reverse();
|
||||
const tweets = usePreloadedQuery(preloadedTestimonialsTweet);
|
||||
const videosReversed = [...videos].reverse();
|
||||
|
||||
const getResponsiveColumns = (numCols: number) => {
|
||||
const columns: string[][] = Array(numCols)
|
||||
@@ -138,7 +135,7 @@ export default function Testimonials({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mb-12 w-full max-w-full overflow-hidden px-4">
|
||||
<div className="w-full max-w-full overflow-hidden px-4">
|
||||
<div className="mb-8">
|
||||
<div className="mb-6 flex flex-wrap items-center justify-between gap-2 sm:flex-nowrap">
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -149,7 +146,7 @@ export default function Testimonials({
|
||||
</div>
|
||||
<div className="hidden h-px flex-1 bg-border sm:block" />
|
||||
<span className="w-full text-right text-muted-foreground text-xs sm:w-auto sm:text-left">
|
||||
[{videos.length} ENTRIES]
|
||||
[{videosReversed.length} ENTRIES]
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -160,7 +157,7 @@ export default function Testimonials({
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
>
|
||||
{videos.map((video, index) => (
|
||||
{videosReversed.map((video, index) => (
|
||||
<VideoCard
|
||||
key={`video-${video.embedId}`}
|
||||
video={video}
|
||||
@@ -177,7 +174,7 @@ export default function Testimonials({
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
>
|
||||
{videos.map((video, index) => (
|
||||
{videosReversed.map((video, index) => (
|
||||
<VideoCard
|
||||
key={`video-${video.embedId}`}
|
||||
video={video}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { api } from "@better-t-stack/backend/convex/_generated/api";
|
||||
import { preloadQuery } from "convex/nextjs";
|
||||
import { fetchQuery } from "convex/nextjs";
|
||||
import CommandSection from "./_components/command-section";
|
||||
import Footer from "./_components/footer";
|
||||
import HeroSection from "./_components/hero-section";
|
||||
@@ -8,13 +8,14 @@ import StatsSection from "./_components/stats-section";
|
||||
import Testimonials from "./_components/testimonials";
|
||||
|
||||
export default async function HomePage() {
|
||||
const preloadedSponsors = await preloadQuery(api.sponsors.getSponsors);
|
||||
const preloadedTestimonialsTweet = await preloadQuery(
|
||||
api.testimonials.getTweets,
|
||||
);
|
||||
const preloadedTestimonialsVideos = await preloadQuery(
|
||||
api.testimonials.getVideos,
|
||||
);
|
||||
const sponsors = await fetchQuery(api.sponsors.getSponsors);
|
||||
const fetchedTweets = await fetchQuery(api.testimonials.getTweets);
|
||||
const fetchedVideos = await fetchQuery(api.testimonials.getVideos);
|
||||
const videos = fetchedVideos.map((v) => ({
|
||||
embedId: v.embedId,
|
||||
title: v.title,
|
||||
}));
|
||||
const tweets = fetchedTweets.map((t) => ({ tweetId: t.tweetId }));
|
||||
|
||||
const minimalAnalytics = await fetch(
|
||||
"https://r2.better-t-stack.dev/analytics-minimal.json",
|
||||
@@ -23,18 +24,15 @@ export default async function HomePage() {
|
||||
const minimalAnalyticsData = await minimalAnalytics.json();
|
||||
|
||||
return (
|
||||
<div className="mx-auto min-h-svh max-w-[1280px]">
|
||||
<main className="mx-auto px-4 pt-12">
|
||||
<main className="mx-auto min-h-svh max-w-[1280px]">
|
||||
<div className="mx-auto flex flex-col gap-8 px-4 pt-12">
|
||||
<HeroSection />
|
||||
<CommandSection />
|
||||
<StatsSection analyticsData={minimalAnalyticsData} />
|
||||
<SponsorsSection preloadedSponsors={preloadedSponsors} />
|
||||
<Testimonials
|
||||
preloadedTestimonialsTweet={preloadedTestimonialsTweet}
|
||||
preloadedTestimonialsVideos={preloadedTestimonialsVideos}
|
||||
/>
|
||||
</main>
|
||||
<SponsorsSection sponsors={sponsors} />
|
||||
<Testimonials tweets={tweets} videos={videos} />
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
"use client";
|
||||
|
||||
import type { api } from "@better-t-stack/backend/convex/_generated/api";
|
||||
import { type Preloaded, usePreloadedQuery } from "convex/react";
|
||||
import { Terminal } from "lucide-react";
|
||||
import Footer from "../../_components/footer";
|
||||
import ShowcaseItem from "../_components/ShowcaseItem";
|
||||
|
||||
export default function ShowcasePage({
|
||||
preloadedShowcase,
|
||||
}: {
|
||||
preloadedShowcase: Preloaded<typeof api.showcase.getShowcaseProjects>;
|
||||
}) {
|
||||
const showcaseProjects = usePreloadedQuery(preloadedShowcase);
|
||||
type ShowcaseProject = {
|
||||
_id: string;
|
||||
_creationTime: number;
|
||||
title: string;
|
||||
description: string;
|
||||
imageUrl: string;
|
||||
liveUrl: string;
|
||||
tags: string[];
|
||||
};
|
||||
|
||||
export default function ShowcasePage({
|
||||
showcaseProjects,
|
||||
}: {
|
||||
showcaseProjects: Array<ShowcaseProject>;
|
||||
}) {
|
||||
return (
|
||||
<main className="mx-auto min-h-svh max-w-[1280px]">
|
||||
<div className="container mx-auto space-y-8 px-4 py-8 pt-16">
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { api } from "@better-t-stack/backend/convex/_generated/api";
|
||||
import { preloadQuery } from "convex/nextjs";
|
||||
import { fetchQuery } from "convex/nextjs";
|
||||
import ShowcasePage from "./_components/showcase-page";
|
||||
|
||||
export default async function Showcase() {
|
||||
const preloadedShowcase = await preloadQuery(
|
||||
api.showcase.getShowcaseProjects,
|
||||
);
|
||||
return <ShowcasePage preloadedShowcase={preloadedShowcase} />;
|
||||
const showcaseProjects = await fetchQuery(api.showcase.getShowcaseProjects);
|
||||
return <ShowcasePage showcaseProjects={showcaseProjects} />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user