mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-28 05:25:33 +00:00
completely remove waitlist (#404)
This commit is contained in:
parent
31463406ce
commit
48e23c13ed
5 changed files with 34 additions and 287 deletions
|
|
@ -510,7 +510,7 @@ const MemoryGraphPage = () => {
|
|||
variant="consumer"
|
||||
>
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<ConnectAIModal
|
||||
<ConnectAIModal
|
||||
onOpenChange={setShowConnectAIModal}
|
||||
open={showConnectAIModal}
|
||||
>
|
||||
|
|
@ -566,7 +566,7 @@ const MemoryGraphPage = () => {
|
|||
totalLoaded={totalLoaded}
|
||||
>
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<ConnectAIModal
|
||||
<ConnectAIModal
|
||||
onOpenChange={setShowConnectAIModal}
|
||||
open={showConnectAIModal}
|
||||
>
|
||||
|
|
@ -714,23 +714,6 @@ export default function Page() {
|
|||
const router = useRouter();
|
||||
const { user } = useAuth();
|
||||
|
||||
const { data: waitlistStatus, isLoading: isCheckingWaitlist } = useQuery({
|
||||
queryKey: ["waitlist-status", user?.id],
|
||||
queryFn: async () => {
|
||||
try {
|
||||
const response = await $fetch("@get/waitlist/status");
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error("Error checking waitlist status:", error);
|
||||
// Return null to indicate error, will handle in useEffect
|
||||
return null;
|
||||
}
|
||||
},
|
||||
enabled: !!user && !user.isAnonymous,
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
retry: 1, // Only retry once on failure
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// save the token for chrome extension
|
||||
const url = new URL(window.location.href);
|
||||
|
|
@ -744,14 +727,8 @@ export default function Page() {
|
|||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (waitlistStatus && !waitlistStatus.accessGranted) {
|
||||
router.push("/waitlist");
|
||||
}
|
||||
}, [waitlistStatus, router]);
|
||||
|
||||
// Show loading state while checking authentication and waitlist status
|
||||
if (!user || isCheckingWaitlist) {
|
||||
if (!user) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-[#0f1419]">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ export default function ReferralPage() {
|
|||
const params = useParams();
|
||||
const referralCode = params.code as string;
|
||||
|
||||
const [isJoiningWaitlist, setIsJoiningWaitlist] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [referralData, setReferralData] = useState<{
|
||||
referrerName?: string;
|
||||
|
|
@ -56,18 +55,7 @@ export default function ReferralPage() {
|
|||
checkReferral();
|
||||
}, [referralCode]);
|
||||
|
||||
const handleJoinWaitlist = async () => {
|
||||
setIsJoiningWaitlist(true);
|
||||
try {
|
||||
// Redirect to waitlist signup with referral code
|
||||
router.push(`/waitlist?ref=${referralCode}`);
|
||||
} catch (error) {
|
||||
console.error("Error joining waitlist:", error);
|
||||
toast.error("Failed to join waitlist. Please try again.");
|
||||
} finally {
|
||||
setIsJoiningWaitlist(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleCopyLink = async () => {
|
||||
try {
|
||||
|
|
@ -158,17 +146,6 @@ export default function ReferralPage() {
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
onClick={handleJoinWaitlist}
|
||||
disabled={isJoiningWaitlist}
|
||||
className="w-full bg-orange-500 hover:bg-orange-600 text-white"
|
||||
>
|
||||
{isJoiningWaitlist ? (
|
||||
<LoaderIcon className="w-4 h-4 animate-spin" />
|
||||
) : (
|
||||
"Join the Waitlist"
|
||||
)}
|
||||
</Button>
|
||||
|
||||
<div className="text-center">
|
||||
<Link
|
||||
|
|
|
|||
|
|
@ -40,17 +40,10 @@ export default function ReferralHomePage() {
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
asChild
|
||||
className="w-full bg-orange-500 hover:bg-orange-600 text-white"
|
||||
>
|
||||
<Link href="/waitlist">Join the Waitlist</Link>
|
||||
</Button>
|
||||
|
||||
<div className="text-center">
|
||||
<Link
|
||||
href="https://supermemory.ai"
|
||||
className="text-orange-500 hover:text-orange-400 text-sm underline"
|
||||
href="https://supermemory.ai"
|
||||
>
|
||||
Learn more about supermemory
|
||||
</Link>
|
||||
|
|
|
|||
|
|
@ -1,216 +0,0 @@
|
|||
"use client";
|
||||
|
||||
import { $fetch } from "@lib/api";
|
||||
import { authClient } from "@lib/auth";
|
||||
import { useAuth } from "@lib/auth-context";
|
||||
import { fetchConsumerProProduct } from "@lib/queries";
|
||||
import { Button } from "@ui/components/button";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@ui/components/card";
|
||||
import { useCustomer } from "autumn-js/react";
|
||||
import { Clock, LoaderIcon, LogOut, SkipForwardIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export default function WaitlistPage() {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const referralCode = searchParams.get("ref");
|
||||
const { user } = useAuth();
|
||||
const [isChecking, setIsChecking] = useState(true);
|
||||
const [isSkippingWaitlist, setIsSkippingWaitlist] = useState(false);
|
||||
const [waitlistStatus, setWaitlistStatus] = useState<{
|
||||
inWaitlist: boolean;
|
||||
accessGranted: boolean;
|
||||
createdAt: string;
|
||||
} | null>(null);
|
||||
const autumn = useCustomer();
|
||||
|
||||
const { data: earlyAccess } = fetchConsumerProProduct(autumn);
|
||||
|
||||
const handleSkipWaitlist = async () => {
|
||||
setIsSkippingWaitlist(true);
|
||||
try {
|
||||
const res = await autumn.attach({
|
||||
productId: "consumer_pro",
|
||||
forceCheckout: true,
|
||||
successUrl: "https://app.supermemory.ai/",
|
||||
});
|
||||
if (res.data && "checkout_url" in res.data && res.data.checkout_url) {
|
||||
router.push(res.data.checkout_url);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error skipping waitlist:", error);
|
||||
} finally {
|
||||
setIsSkippingWaitlist(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
await authClient.signOut();
|
||||
router.push("/");
|
||||
} catch (error) {
|
||||
console.error("Error signing out:", error);
|
||||
toast.error("Failed to sign out");
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
async function checkAccess() {
|
||||
if (!user) {
|
||||
router.push("/");
|
||||
return;
|
||||
}
|
||||
|
||||
// Anonymous users should sign in first
|
||||
if (user.isAnonymous) {
|
||||
authClient.signOut();
|
||||
router.push("/");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Check waitlist status using the new endpoint
|
||||
const response = await $fetch("@get/waitlist/status");
|
||||
|
||||
if (response.data) {
|
||||
setWaitlistStatus(response.data);
|
||||
|
||||
if (!response.data.inWaitlist) {
|
||||
authClient.signOut();
|
||||
router.push("/login");
|
||||
}
|
||||
|
||||
// If user has access, redirect to home
|
||||
if (response.data.accessGranted) {
|
||||
router.push("/");
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error checking waitlist status:", error);
|
||||
// If there's an error, assume user is on waitlist
|
||||
setWaitlistStatus({
|
||||
inWaitlist: true,
|
||||
accessGranted: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
});
|
||||
} finally {
|
||||
setIsChecking(false);
|
||||
}
|
||||
}
|
||||
|
||||
checkAccess();
|
||||
}, [user, router]);
|
||||
|
||||
if (isChecking) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center p-4 bg-[#0f1419]">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<LoaderIcon className="w-8 h-8 text-orange-500 animate-spin" />
|
||||
<p className="text-white/60">Checking access...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center p-4 bg-[#0f1419]">
|
||||
<Card className="max-w-md w-full bg-[#1a1f2a] border-white/10">
|
||||
<CardHeader className="text-center">
|
||||
<div className="mx-auto mb-4 w-16 h-16 rounded-full bg-orange-500/10 flex items-center justify-center">
|
||||
<Clock className="w-8 h-8 text-orange-500" />
|
||||
</div>
|
||||
<CardTitle className="text-2xl font-bold text-white">
|
||||
You're on the waitlist!
|
||||
</CardTitle>
|
||||
<CardDescription className="text-white/60 mt-2">
|
||||
{referralCode
|
||||
? "Thanks for joining through a friend's invitation! You've been added to the waitlist with priority access."
|
||||
: "Thanks for your interest in supermemory. We'll notify you as soon as we're ready for you."}
|
||||
</CardDescription>
|
||||
{referralCode && (
|
||||
<div className="mt-3 px-3 py-2 bg-orange-500/10 rounded-lg border border-orange-500/20">
|
||||
<p className="text-orange-400 text-sm font-medium">
|
||||
🎉 Referred by a friend! You'll get priority access.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex flex-col gap-4">
|
||||
{!earlyAccess?.allowed && (
|
||||
<Button
|
||||
disabled={isSkippingWaitlist}
|
||||
onClick={handleSkipWaitlist}
|
||||
>
|
||||
{isSkippingWaitlist ? (
|
||||
<LoaderIcon className="w-4 h-4 animate-spin" />
|
||||
) : (
|
||||
<SkipForwardIcon className="w-4 h-4" />
|
||||
)}
|
||||
{isSkippingWaitlist
|
||||
? "Processing..."
|
||||
: "Skip the waitlist for $15"}
|
||||
</Button>
|
||||
)}
|
||||
<div className="pt-4 border-t border-white/10">
|
||||
<p className="text-white/60 text-sm">
|
||||
We're working hard to bring you the best experience. In the
|
||||
meantime, you can:
|
||||
</p>
|
||||
<ul className="mt-3 space-y-2 text-sm">
|
||||
<li className="flex items-center gap-2 text-white/80">
|
||||
<span className="text-orange-500">•</span>
|
||||
<a
|
||||
className="hover:text-white transition-colors underline"
|
||||
href="https://x.com/supermemoryai"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Follow our X for updates
|
||||
</a>
|
||||
</li>
|
||||
<li className="flex items-center gap-2 text-white/80">
|
||||
<span className="text-orange-500">•</span>
|
||||
<a
|
||||
className="hover:text-white transition-colors underline"
|
||||
href="https://supermemory.link/discord"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
Join our community Discord
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{user && (
|
||||
<div className="pt-4 text-center space-y-3">
|
||||
<p className="text-white/50 text-xs">
|
||||
Signed in as {user.email}
|
||||
</p>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleLogout}
|
||||
className="border-white/20 hover:bg-white/5"
|
||||
>
|
||||
<LogOut className="w-4 h-4 mr-2" />
|
||||
Sign out
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -5,7 +5,15 @@ import { cn } from "@lib/utils";
|
|||
import { Button } from "@ui/components/button";
|
||||
import { Input } from "@ui/components/input";
|
||||
import { DefaultChatTransport } from "ai";
|
||||
import { ArrowUp, Check, Copy, RotateCcw, X, ChevronDown, ChevronRight } from "lucide-react";
|
||||
import {
|
||||
ArrowUp,
|
||||
Check,
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
Copy,
|
||||
RotateCcw,
|
||||
X,
|
||||
} from "lucide-react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { Streamdown } from "streamdown";
|
||||
|
|
@ -41,8 +49,9 @@ function ExpandableMemories({ foundCount, results }: ExpandableMemoriesProps) {
|
|||
return (
|
||||
<div className="text-sm">
|
||||
<button
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
className="flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors"
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
type="button"
|
||||
>
|
||||
{isExpanded ? (
|
||||
<ChevronDown className="size-4" />
|
||||
|
|
@ -52,12 +61,15 @@ function ExpandableMemories({ foundCount, results }: ExpandableMemoriesProps) {
|
|||
<Check className="size-4" />
|
||||
Found {foundCount} {foundCount === 1 ? "memory" : "memories"}
|
||||
</button>
|
||||
|
||||
|
||||
{isExpanded && results.length > 0 && (
|
||||
<div className="mt-2 ml-6 space-y-2 max-h-48 overflow-y-auto">
|
||||
{results.map((result, index) => {
|
||||
const isClickable = result.url && (result.url.startsWith('http://') || result.url.startsWith('https://'));
|
||||
|
||||
const isClickable =
|
||||
result.url &&
|
||||
(result.url.startsWith("http://") ||
|
||||
result.url.startsWith("https://"));
|
||||
|
||||
const content = (
|
||||
<>
|
||||
{result.title && (
|
||||
|
|
@ -86,11 +98,11 @@ function ExpandableMemories({ foundCount, results }: ExpandableMemoriesProps) {
|
|||
if (isClickable) {
|
||||
return (
|
||||
<a
|
||||
key={result.documentId || index}
|
||||
href={result.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="block p-2 bg-white/5 rounded-md border border-white/10 hover:bg-white/10 hover:border-white/20 transition-colors cursor-pointer"
|
||||
href={result.url}
|
||||
key={result.documentId || index}
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
{content}
|
||||
</a>
|
||||
|
|
@ -99,8 +111,8 @@ function ExpandableMemories({ foundCount, results }: ExpandableMemoriesProps) {
|
|||
|
||||
return (
|
||||
<div
|
||||
key={result.documentId || index}
|
||||
className="p-2 bg-white/5 rounded-md border border-white/10"
|
||||
key={result.documentId || index}
|
||||
>
|
||||
{content}
|
||||
</div>
|
||||
|
|
@ -376,12 +388,16 @@ export function ChatMessages() {
|
|||
"count" in output
|
||||
? Number(output.count) || 0
|
||||
: 0;
|
||||
const results = Array.isArray(output?.results) ? output.results : [];
|
||||
|
||||
// @ts-expect-error
|
||||
const results = Array.isArray(output?.results)
|
||||
? // @ts-expect-error
|
||||
output.results
|
||||
: [];
|
||||
|
||||
return (
|
||||
<ExpandableMemories
|
||||
key={message.id + part.type}
|
||||
foundCount={foundCount}
|
||||
key={message.id + part.type}
|
||||
results={results}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue