Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
created top-up-interface
  • Loading branch information
pruthvi-yb committed Sep 21, 2024
commit 5055d9104daf248bfdd8e8feceb57727f61e881a
2 changes: 2 additions & 0 deletions app/(default)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import AOS from "aos";
import "aos/dist/aos.css";

import PageIllustration from "@/components/page-illustration";
import Footer from "@/components/footer";

export default function DefaultLayout({
children,
Expand All @@ -27,6 +28,7 @@ export default function DefaultLayout({
<PageIllustration />
{children}
</main>
<Footer />
</>
);
}
2 changes: 2 additions & 0 deletions app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { format, parseISO } from "date-fns";
import Image from "next/image";
import { notFound } from "next/navigation";
import { posts } from "@/lib/blog/postData";
import Footer from "@/components/footer";

export const generateStaticParams = async () =>
posts.map((post) => ({ slug: post.url.split("/").pop() }));
Expand Down Expand Up @@ -83,6 +84,7 @@ const PostLayout = ({ params }: { params: { slug: string } }) => {
dangerouslySetInnerHTML={{ __html: post.content }}
/>
</article>
<Footer />
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
Expand Down
2 changes: 2 additions & 0 deletions app/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { constructMetadata } from "@/lib/utils";
import { compareDesc } from "date-fns";
import { Metadata } from "next";
import { posts } from "@/lib/blog/postData";
import Footer from "@/components/footer";

export const metadata: Metadata = constructMetadata({
title: "Blog",
Expand All @@ -25,6 +26,7 @@ export default function Blog() {
<PostCard key={idx} {...post} />
))}
</div>
<Footer />
</div>
);
}
2 changes: 2 additions & 0 deletions app/faq/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Link from "next/link";
import { constructMetadata } from "@/lib/utils";
import { Metadata } from "next/types";
import { FAQItem } from "@/types/faqItems";
import Footer from "@/components/footer";

export const metadata: Metadata = constructMetadata({
title: "FAQ",
Expand Down Expand Up @@ -76,6 +77,7 @@ const FAQ: React.FC = () => {
</AccordionItem>
</Accordion>
</section>
<Footer />
</>
);
};
Expand Down
2 changes: 0 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import dynamic from "next/dynamic";
import { Analytics } from "@vercel/analytics/react";
import { SpeedInsights } from "@vercel/speed-insights/next";
import { ThemeProvider } from "next-themes";
import Footer from "@/components/footer";

const PostHogPageView = dynamic(() => import("./PostHogPageView"), {
ssr: false,
Expand All @@ -36,7 +35,6 @@ export default function RootLayout({
<div className="flex min-h-screen flex-col overflow-hidden">
<Header />
{children}
<Footer />
<Toaster position="bottom-right" richColors />
<Analytics />
<SpeedInsights />
Expand Down
2 changes: 2 additions & 0 deletions components/about.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Card, CardContent, CardDescription } from "@/components/ui/card";
import { Tweet } from "@/components/tweet";
import { components } from "./ui/my-tweet";
import { Badge } from "./ui/badge";
import Footer from "./footer";

type VideoData = {
src: string;
Expand Down Expand Up @@ -122,6 +123,7 @@ const AboutComponent: React.FC = () => {
</p>
</div>
</div>
<Footer />
</section>
);
};
Expand Down
139 changes: 139 additions & 0 deletions components/buy-credits-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { useState, useEffect } from "react";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Slider } from "@/components/ui/slider";
import { CreditCard, DollarSign } from "lucide-react";

const QUICK_AMOUNTS = [10, 20, 50, 80];
const MIN_AMOUNT = 5;
const MAX_AMOUNT = 80;
const CREDIT_PRICE = 0.1; // 10 cents per credit

export default function BuyCreditsModal() {
const [amount, setAmount] = useState<string>("10");
const [isOpen, setIsOpen] = useState(false);

useEffect(() => {
const numericAmount = Number(amount);
if (numericAmount < MIN_AMOUNT) setAmount(MIN_AMOUNT.toString());
if (numericAmount > MAX_AMOUNT) setAmount(MAX_AMOUNT.toString());
}, [amount]);

const handleAmountChange = (value: string) => {
if (
value === "" ||
(Number(value) >= MIN_AMOUNT && Number(value) <= MAX_AMOUNT)
) {
setAmount(value);
}
};

const handleSliderChange = (value: number[]) => {
setAmount(value[0].toString());
};

const handleQuickAmountSelect = (quickAmount: number) => {
setAmount(quickAmount.toString());
};

const handleBuyCredits = () => {
const numericAmount = Number(amount);
if (numericAmount >= MIN_AMOUNT && numericAmount <= MAX_AMOUNT) {
const creditsAmount = Math.floor(numericAmount / CREDIT_PRICE);
console.log(`Purchased ${creditsAmount} credits for $${numericAmount}`);
setIsOpen(false);
} else {
console.error(`Invalid amount: $${numericAmount}`);
}
};

return (
<AlertDialog open={isOpen} onOpenChange={setIsOpen}>
<AlertDialogTrigger asChild>
<Button variant="outline">Buy Extra Credits</Button>
</AlertDialogTrigger>
<AlertDialogContent className="max-w-sm sm:max-w-md">
<AlertDialogHeader>
<AlertDialogTitle className="text-2xl font-bold">
Buy Extra Credits
</AlertDialogTitle>
<AlertDialogDescription className="text-gray-600 dark:text-gray-500">
Purchase additional credits to continue using AI prompts.
</AlertDialogDescription>
</AlertDialogHeader>
<div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="amount" className="text-right">
Amount ($)
</Label>
<Input
id="amount"
type="number"
value={amount}
onChange={(e) => handleAmountChange(e.target.value)}
min={MIN_AMOUNT}
max={MAX_AMOUNT}
className="col-span-3 bg-gray-600/10 dark:bg-gray-300/10"
/>
</div>
<Slider
value={[Number(amount)]}
onValueChange={handleSliderChange}
max={MAX_AMOUNT}
min={MIN_AMOUNT}
step={1}
className="mt-2"
/>
<div className="flex items-center justify-between">
<span className="text-sm text-gray-600 dark:text-gray-500">
${MIN_AMOUNT}
</span>
<span className="text-sm text-gray-600 dark:text-gray-500">
${MAX_AMOUNT}
</span>
</div>
<div className="mt-4 flex justify-center space-x-2">
{QUICK_AMOUNTS.map((quickAmount) => (
<Button
key={quickAmount}
variant="outline"
size="sm"
onClick={() => handleQuickAmountSelect(quickAmount)}
>
${quickAmount}
</Button>
))}
</div>
<div className="mt-4 flex items-center justify-between rounded-lg bg-gray-500/10 p-4 dark:bg-gray-300/10">
<div className="flex items-center">
<CreditCard className="mr-2 h-4 w-4" />
<span className="text-sm font-medium">Credits to receive:</span>
</div>
<span className="text-2xl font-bold">
{amount ? Math.floor(Number(amount) / CREDIT_PRICE) : 0}
</span>
</div>
</div>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={handleBuyCredits}>
<DollarSign className="h-4 w-4" />
Buy Credits
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}
12 changes: 6 additions & 6 deletions components/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,18 @@ export default function DashboardPage({
<ProfileCard user={user} />
{/* Below commented out until we implement Free Trial */}
{subscription ? (
<SubscriptionCard
subscription={subscription}
<FreeTrialCard
loading={loading}
usage={usage}
openAppQueryParams={openAppQueryParams}
user={user}
loading={loading}
/>
) : (
<FreeTrialCard
loading={loading}
<SubscriptionCard
subscription={subscription}
usage={usage}
openAppQueryParams={openAppQueryParams}
user={user}
loading={loading}
/>
)}
</div>
Expand Down
4 changes: 4 additions & 0 deletions components/dashboard/subscription-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { Info } from "lucide-react";
import { UsageType } from "../dashboard";
import { toast } from "sonner";
import { useUpgradeSubscription } from "@/hooks/useUpgradeSubscription";
import BuyCreditsModal from "../buy-credits-modal";

type SubscriptionCardProps = {
subscription: Subscription | null;
Expand Down Expand Up @@ -311,6 +312,9 @@ export default function SubscriptionCard({
Use this button to open the app and login directly.
</p>
</div>
<div className="mt-4">
<BuyCreditsModal />
</div>
</CardContent>
</div>
</Card>
Expand Down
2 changes: 2 additions & 0 deletions components/pricing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
import { Info } from "lucide-react";
import Spinner from "./ui/spinner";
import Link from "next/link";
import Footer from "./footer";

interface ExtendedPricingTierProps extends PricingTierProps {
disabled?: boolean;
Expand Down Expand Up @@ -480,6 +481,7 @@ const PricingPage: React.FC<PricingPageProps> = ({ user }) => {
</Tabs>
</div>
</div>
<Footer />
</section>
);
};
Expand Down
2 changes: 1 addition & 1 deletion components/ui/alert-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const AlertDialogContent = React.forwardRef<
<AlertDialogPrimitive.Content
ref={ref}
className={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
className,
)}
{...props}
Expand Down
4 changes: 2 additions & 2 deletions components/ui/slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ const Slider = React.forwardRef<
)}
{...props}
>
<SliderPrimitive.Track className="bg-secondary relative h-2 w-full grow overflow-hidden rounded-full">
<SliderPrimitive.Range className="absolute h-full bg-primary" />
<SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-gray-700/10 dark:bg-gray-700/10">
<SliderPrimitive.Range className="absolute h-full bg-black dark:bg-white-100" />
</SliderPrimitive.Track>
<SliderPrimitive.Thumb className="block h-5 w-5 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" />
</SliderPrimitive.Root>
Expand Down
Loading