Skip to content

NIXBLACK11/animos

Repository files navigation

"Σκέψη Ελεύθερη, Γνώση Αιώνια" (Free Thought, Eternal Knowledge)

"use client"

import { useMotionValueEvent, useScroll } from "framer-motion";
import { useRef, useState, useEffect } from "react";

export const Features = () => {
    const containerRef = useRef<HTMLDivElement>(null);
    const textContainerRef = useRef<HTMLDivElement>(null);

    const textH = `This is the speed we normally type at: The quick brown fox jumpd over the lazt dog in a hurry to get to it's den.`;
    const [prevTextH, setPrevTextH] = useState("");
    const [nextTextH, setNextTextH] = useState(textH);
    
    const textA = `But with AI assistance, you can write faster, more accurately, and with greater creativity. Like this: The quick brown fox jumped over the lazy dog in a hurry to get to its den, moving swiftly under the golden evening sky.`;
    const [prevTextA, setPrevTextA] = useState("");
    const [nextTextA, setNextTextA] = useState(textA);

    const [isVisible, setIsVisible] = useState(false);

    const { scrollYProgress } = useScroll({
        target: containerRef,
        offset: ["start end", "end start"]
    });

    useEffect(() => {
        const observer = new IntersectionObserver(
            ([entry]) => {
                setIsVisible(entry.isIntersecting);
            },
            {
                root: null,
                threshold: 0.9,
            }
        );

        if (containerRef.current) {
            observer.observe(containerRef.current);
        }

        return () => observer.disconnect();
    }, []);

    useMotionValueEvent(scrollYProgress, "change", (value) => {
        if (!isVisible) return;
        
        // Human text progress (slower)
        const humanProgress = Math.min(value * 1, 1); // Slows down human text
        const totalLengthH = textH.length;
        const scrollIndexH = Math.floor(humanProgress * totalLengthH);

        const updatedPrevTextH = textH.slice(0, scrollIndexH);
        const updatedNextTextH = textH.slice(scrollIndexH);

        setPrevTextH(updatedPrevTextH);
        setNextTextH(updatedNextTextH);

        // AI text progress (4x faster)
        const aiProgress = Math.min(value * 3, 1); // Makes AI text 4x faster than human text
        const totalLengthA = textA.length;
        const scrollIndexA = Math.floor(aiProgress * totalLengthA);

        const updatedPrevTextA = textA.slice(0, scrollIndexA);
        const updatedNextTextA = textA.slice(scrollIndexA);

        setPrevTextA(updatedPrevTextA);
        setNextTextA(updatedNextTextA);
    });

    return (
        <div
            ref={containerRef}
            className="bg-[#000000] w-full h-[400vh] flex items-start justify-center"
        >
            <div 
                ref={textContainerRef}
                className={`sticky top-10 w-3/4 h-[400px] flex flex-col items-start justify-center transition-opacity duration-300 text-4xl font-bold ${
                    isVisible ? 'opacity-100' : 'opacity-0'
                }`}
            >
                <div className="mb-20">
                    <span className="text-white">
                        {prevTextH}
                    </span>
                    <span className="text-neutral-800">
                        {nextTextH}
                    </span>
                </div>
                <div>
                    <span className="text-white">
                        {prevTextA}
                    </span>
                    <span className="text-neutral-800">
                        {nextTextA}
                    </span>
                </div>
            </div>
        </div>
    );
};

export default Features;
import { NextRequest, NextResponse } from "next/server";
import Stripe from "stripe";
import { createClient } from "@supabase/supabase-js";

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string, {
  apiVersion: "2023-10-16",
});

const supabase = createClient(
  process.env.SUPABASE_URL as string,
  process.env.SUPABASE_SERVICE_ROLE_KEY as string
);

export async function POST(req: NextRequest) {
  const sig = req.headers.get("stripe-signature");
  const rawBody = await req.text();

  try {
    // Verify Stripe signature
    const event = stripe.webhooks.constructEvent(
      rawBody,
      sig as string,
      process.env.STRIPE_WEBHOOK_SECRET as string
    );

    if (event.type === "checkout.session.completed") {
      const session = event.data.object as Stripe.Checkout.Session;
      const userId = session.metadata?.user_id;
      const tier = session.metadata?.tier_name;
      
      if (!userId || !tier) {
        return NextResponse.json({ error: "Missing user_id or tier_name" }, { status: 400 });
      }

      const validTill = new Date();
      validTill.setMonth(validTill.getMonth() + 1); // Set expiration 1 month ahead

      const { error } = await supabase.from("user_tiers").upsert({
        id: userId,
        tier_name: tier,
        valid_till: validTill.toISOString(),
      });

      if (error) {
        console.error("Supabase error:", error);
        return NextResponse.json({ error: "Failed to update user tier" }, { status: 500 });
      }

      console.log(`Updated user ${userId} to tier ${tier} until ${validTill.toISOString()}`);
    }

    return NextResponse.json({ received: true });
  } catch (err: any) {
    console.error("Webhook error:", err.message);
    return NextResponse.json({ error: "Webhook error" }, { status: 400 });
  }
}