Skip to content

Commit

Permalink
feat: added embed
Browse files Browse the repository at this point in the history
  • Loading branch information
Shashivadan committed Nov 16, 2024
1 parent 5154fc9 commit 6d18220
Show file tree
Hide file tree
Showing 29 changed files with 861 additions and 47 deletions.
15 changes: 13 additions & 2 deletions apps/embed-v1/next.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { fileURLToPath } from "url";
import createJiti from "jiti";
import { createJiti } from "jiti";

// Import env files to validate at build time. Use jiti so we can load .ts files in here.
createJiti(fileURLToPath(import.meta.url))("./src/env");
await createJiti(fileURLToPath(import.meta.url)).import("./src/env");

/** @type {import("next").NextConfig} */
const config = {
Expand All @@ -20,6 +20,17 @@ const config = {
/** We already do linting and typechecking as separate tasks in CI */
eslint: { ignoreDuringBuilds: true },
typescript: { ignoreBuildErrors: true },
images: {
remotePatterns: [
{
protocol: "https",
hostname: "loremflickr.com",
port: "",
pathname: "/**",
},
],
unoptimized: true,
},
};

export default config;
31 changes: 31 additions & 0 deletions apps/embed-v1/src/actions/getOrgTestimonials.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"use server";

import { eq } from "@acme/db";
import { db } from "@acme/db/client";

import type {
OrganizationTestimonialType,
TestimonialTableType,
} from "~/types/schema-types";

export async function getOrgTestimonials(org: string) {
try {
const data = (await db.query.organizationTable.findMany({
where: (organizationTable, { eq }) =>
eq(organizationTable.organizationName, org),
with: {
testimonials: {
where: (testimonialsTable: TestimonialTableType) =>
eq(testimonialsTable.wallOfFame, true),
},
},
})) as OrganizationTestimonialType[];

if (data.length === 0) {
return "Project not found";
}
return data[0];
} catch (error) {
return (error as Error).message;
}
}
6 changes: 0 additions & 6 deletions apps/embed-v1/src/app/[orgName]/page.tsx

This file was deleted.

68 changes: 42 additions & 26 deletions apps/embed-v1/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,62 @@
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--foreground: 250 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--card-foreground: 250 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--primary: 327 66% 69%;
--primary-foreground: 337 65.5% 17.1%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--popover-foreground: 250 10% 3.9%;
--primary: 267 75% 64%;
--primary-foreground: 0 0% 100%;
--secondary: 250 4.8% 95.9%;
--secondary-foreground: 250 5.9% 10%;
--muted: 250 4.8% 95.9%;
--muted-foreground: 250 3.8% 46.1%;
--accent: 267 75% 95.9%;
--accent-foreground: 250 5.9% 10%;
--destructive: 0 72.22% 50.59%;
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 5% 64.9%;
--border: 250 5.9% 90%;
--input: 250 5.9% 90%;
--ring: 267 75% 64%;
--radius: 0.5rem;
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}

.dark {
--background: 240 10% 3.9%;
--background: 250 10% 3.9%;
--foreground: 0 0% 98%;
--card: 240 10% 3.9%;
--card: 250 10% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 240 10% 3.9%;
--popover: 250 10% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 327 66% 69%;
--primary-foreground: 337 65.5% 17.1%;
--secondary: 240 3.7% 15.9%;
--primary: 267 75% 64%;
--primary-foreground: 0 0% 100%;
--secondary: 250 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--accent: 240 3.7% 15.9%;
--muted: 250 3.7% 15.9%;
--muted-foreground: 250 5% 64.9%;
--accent: 267 75% 35%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 85.7% 97.3%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
--border: 250 3.7% 15.9%;
--input: 250 3.7% 15.9%;
--ring: 267 75% 64%;
--sidebar-background: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}
4 changes: 2 additions & 2 deletions apps/embed-v1/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { Metadata, Viewport } from "next";
import { GeistMono } from "geist/font/mono";
import { GeistSans } from "geist/font/sans";
import { ThemeProvider } from "next-themes";

import { cn } from "@acme/ui";
import { ThemeProvider } from "@acme/ui/theme";
import { Toaster } from "@acme/ui/toast";

import { TRPCReactProvider } from "~/trpc/react";
Expand Down Expand Up @@ -50,7 +50,7 @@ export default function RootLayout(props: { children: React.ReactNode }) {
GeistMono.variable,
)}
>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<ThemeProvider attribute="class" defaultTheme="white">
<TRPCReactProvider>{props.children}</TRPCReactProvider>
<Toaster />
</ThemeProvider>
Expand Down
53 changes: 53 additions & 0 deletions apps/embed-v1/src/app/m/[orgName]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from "react";

import NotFound from "@acme/ui/components/404-not-found";

import { getOrgTestimonials } from "~/actions/getOrgTestimonials";
import MarqueeMain from "~/components/marquee-main";
import { ReviewCard } from "~/components/review-card";

export default async function TestimonialsPage({
params,
}: {
params: { orgName: string };
}) {
const { orgName } = params;
const data = await getOrgTestimonials(orgName);

if (!data || typeof data === "string") return <NotFound />;
if (data.testimonials.length === 0) return <NotFound />;

if (data.testimonials.length < 4) {
return (
<div className="h-svh columns-[300px] overflow-hidden">
{data.testimonials.map((testimonial, index) => (
<ReviewCard key={index} data={testimonial} />
))}
</div>
);
}

// Split testimonials into 5 columns for marquee effect
const testimonialsData = data.testimonials.reduce<JSX.Element[][]>(
(acc, testimonial, index) => {
const columnIndex = index % 5;

if (!acc[columnIndex]) {
acc[columnIndex] = [];
}

acc[columnIndex].push(
<ReviewCard
key={`testimonial-${columnIndex}-${index}`}
data={testimonial}
/>,
);
return acc;
},
[],
);

return (
<MarqueeMain data={data.testimonials} testmonials={testimonialsData} />
);
}
6 changes: 5 additions & 1 deletion apps/embed-v1/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export default function HomePage() {
return <main className="">=</main>;
return (
<main className="flex h-svh items-center justify-center">
Nothing to see here
</main>
);
}
79 changes: 79 additions & 0 deletions apps/embed-v1/src/components/marquee-main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"use client";

import React from "react";
import { useSearchParams } from "next/navigation";
import { useTheme } from "next-themes";

import { cn } from "@acme/ui";

import type { TestimonialType } from "~/types/schema-types";
import { Marquee } from "./marquee";
import { ReviewCard } from "./review-card";

export default function MarqueeMain({
testmonials,
data,
}: {
testmonials: JSX.Element[][];
data: TestimonialType[];
}) {
const searchParams = useSearchParams();
const noMarquee = searchParams.get("no-marquee");
const cantainerClassName = searchParams.get("container-classname");
const darkTheme = searchParams.get("darktheme");

const { theme, setTheme } = useTheme();

// http://localhost:3001/m/zenstream?classname=df%20sdf&theme=dark&marquee=%22true%22

React.useEffect(() => {
if (darkTheme) {
setTheme("dark");
} else {
setTheme("light");
}
}, [theme, setTheme, darkTheme]);

if (noMarquee) {
return (
<>
<div className="h-svh w-full columns-[450px] gap-4">
{data.map((item) => (
<ReviewCard
key={item.id}
data={item}
className="mb-4 break-inside-avoid"
/>
))}
{data.map((item) => (
<ReviewCard
key={item.id}
data={item}
className="mb-4 break-inside-avoid"
/>
))}
</div>
</>
);
}

return (
<div
className={cn(
"h-svh columns-[350px] overflow-hidden",
cantainerClassName,
)}
>
{testmonials.map((columnData, columnIndex) => (
<Marquee
key={`marquee-${columnIndex}`}
vertical
reverse={columnIndex % 2 === 1}
className="overflow-hidden [--duration:80s]"
>
{columnData}
</Marquee>
))}
</div>
);
}
51 changes: 51 additions & 0 deletions apps/embed-v1/src/components/marquee.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { cn } from "@acme/ui";

interface MarqueeProps {
className?: string;
reverse?: boolean;
pauseOnHover?: boolean;
children?: React.ReactNode;
vertical?: boolean;
repeat?: number;
[key: string]: unknown;
}

export function Marquee({
className,
reverse,
pauseOnHover = false,
children,
vertical = false,
repeat = 4,
...props
}: MarqueeProps) {
return (
<div
{...props}
className={cn(
"group flex overflow-hidden p-2 [--duration:40s] [--gap:1rem] [gap:var(--gap)]",
{
"flex-row": !vertical,
"flex-col": vertical,
},
className,
)}
>
{Array(repeat)
.fill(0)
.map((_, i) => (
<div
key={i}
className={cn("flex shrink-0 justify-around [gap:var(--gap)]", {
"animate-marquee flex-row": !vertical,
"animate-marquee-vertical flex-col": vertical,
"group-hover:[animation-play-state:paused]": pauseOnHover,
"[animation-direction:reverse]": reverse,
})}
>
{children}
</div>
))}
</div>
);
}
Loading

0 comments on commit 6d18220

Please sign in to comment.