diff --git a/apps/www/src/app/(main)/(dashborad)/products/[id]/(Settings)/edit-this-space/page.tsx b/apps/www/src/app/(main)/(dashborad)/products/[id]/(Settings)/edit-this-space/page.tsx
index bbad24c..eb9a4f2 100644
--- a/apps/www/src/app/(main)/(dashborad)/products/[id]/(Settings)/edit-this-space/page.tsx
+++ b/apps/www/src/app/(main)/(dashborad)/products/[id]/(Settings)/edit-this-space/page.tsx
@@ -13,7 +13,7 @@ export default async function page({ params }: { params: { id: string } }) {
}
return (
-
+
);
diff --git a/apps/www/src/app/(main)/(dashborad)/products/[id]/(embeddings)/embed-doc/page.tsx b/apps/www/src/app/(main)/(dashborad)/products/[id]/(embeddings)/embed-doc/page.tsx
new file mode 100644
index 0000000..88d710d
--- /dev/null
+++ b/apps/www/src/app/(main)/(dashborad)/products/[id]/(embeddings)/embed-doc/page.tsx
@@ -0,0 +1,129 @@
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@acme/ui/card";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@acme/ui/table";
+
+export default function TestimonialEmbedDocs() {
+ const queryParams = [
+ {
+ name: "no-marquee",
+ type: "boolean",
+ description:
+ "When set, displays testimonials in a static grid layout instead of a marquee.",
+ example: "?no-marquee=true",
+ },
+ {
+ name: "container-classname",
+ type: "string",
+ description: "Applies additional CSS classes to the container div.",
+ example: "?container-classname=my-custom-class",
+ },
+ {
+ name: "darktheme",
+ type: "boolean",
+ description: "Forces the dark theme when set.",
+ example: "?darktheme=true",
+ },
+ {
+ name: "theme",
+ type: "string",
+ description: "Sets the theme explicitly. Can be 'light' or 'dark'.",
+ example: "?theme=dark",
+ },
+ {
+ name: "marquee",
+ type: "string",
+ description: "Controls marquee behavior. Set to 'true' to enable.",
+ example: '?marquee="true"',
+ },
+ ];
+
+ return (
+
+
+
+ Testimonial Embed Documentation
+
+ Customize your testimonial embed using these query parameters
+
+
+
+
+
+
+ Parameter
+ Type
+ Description
+ Example
+
+
+
+ {queryParams.map((param) => (
+
+ {param.name}
+ {param.type}
+ {param.description}
+
+ {param.example}
+
+
+ ))}
+
+
+
+
+
Usage Examples
+
+ -
+
http://localhost:3001/m/zenstream?no-marquee=true
+
+ Displays testimonials in a static grid layout
+
+
+ -
+
http://localhost:3001/m/zenstream?darktheme=true
+
+ Forces the dark theme
+
+
+ -
+
+ http://localhost:3001/m/zenstream?container-classname=custom-container&theme=dark&marquee="true"
+
+
+ Applies a custom class, sets dark theme, and enables marquee
+
+
+
+
+
+
+
Notes
+
+ - Parameters can be combined using the & symbol.
+ -
+ Boolean parameters are considered true when present, regardless
+ of their value.
+
+ -
+ The 'theme' parameter takes precedence over 'darktheme' if both
+ are provided.
+
+
+
+
+
+
+ );
+}
diff --git a/apps/www/src/app/(main)/(dashborad)/products/[id]/(embeddings)/embed/page.tsx b/apps/www/src/app/(main)/(dashborad)/products/[id]/(embeddings)/embed/page.tsx
new file mode 100644
index 0000000..3d20cfc
--- /dev/null
+++ b/apps/www/src/app/(main)/(dashborad)/products/[id]/(embeddings)/embed/page.tsx
@@ -0,0 +1,5 @@
+import Embedding from "~/components/embeddings/embedding";
+
+export default function page({ params }: { params: { id: string } }) {
+ return
;
+}
diff --git a/apps/www/src/app/(main)/(dashborad)/products/[id]/(pages)/_components/show-case-links.tsx b/apps/www/src/app/(main)/(dashborad)/products/[id]/(pages)/_components/show-case-links.tsx
index 5a52634..5fca490 100644
--- a/apps/www/src/app/(main)/(dashborad)/products/[id]/(pages)/_components/show-case-links.tsx
+++ b/apps/www/src/app/(main)/(dashborad)/products/[id]/(pages)/_components/show-case-links.tsx
@@ -16,7 +16,7 @@ export default function ShowCaseLink({
const domain = document.location.origin;
return (
-
On our hosted page
+
On our hosted page
{`${domain}/${name}/${page}`}
diff --git a/apps/www/src/app/(main)/(dashborad)/products/[id]/(pages)/request-testimonial/page.tsx b/apps/www/src/app/(main)/(dashborad)/products/[id]/(pages)/request-testimonial/page.tsx
index 0b61ef4..8a8092a 100644
--- a/apps/www/src/app/(main)/(dashborad)/products/[id]/(pages)/request-testimonial/page.tsx
+++ b/apps/www/src/app/(main)/(dashborad)/products/[id]/(pages)/request-testimonial/page.tsx
@@ -4,7 +4,7 @@ import ShowCaseLink from "../_components/show-case-links";
export default function page({ params }: { params: { id: string } }) {
return (
-
+
Request Testimonial
Share this link with your clients or customers to request testimonials
diff --git a/apps/www/src/app/(main)/(dashborad)/products/[id]/(pages)/wall-of-fame/page.tsx b/apps/www/src/app/(main)/(dashborad)/products/[id]/(pages)/wall-of-fame/page.tsx
index a7a77b8..524c279 100644
--- a/apps/www/src/app/(main)/(dashborad)/products/[id]/(pages)/wall-of-fame/page.tsx
+++ b/apps/www/src/app/(main)/(dashborad)/products/[id]/(pages)/wall-of-fame/page.tsx
@@ -4,7 +4,7 @@ import ShowCaseLink from "../_components/show-case-links";
export default function page({ params }: { params: { id: string } }) {
return (
-
+
Wall 0f Fame
share you wall of fame
diff --git a/apps/www/src/app/(main)/(dashborad)/products/[id]/layout.tsx b/apps/www/src/app/(main)/(dashborad)/products/[id]/layout.tsx
index 54ea282..ae54672 100644
--- a/apps/www/src/app/(main)/(dashborad)/products/[id]/layout.tsx
+++ b/apps/www/src/app/(main)/(dashborad)/products/[id]/layout.tsx
@@ -17,9 +17,9 @@ export default async function Layout({
}
return (
-
-
-
+
+
+
diff --git a/apps/www/src/components/embeddings/embedding.tsx b/apps/www/src/components/embeddings/embedding.tsx
new file mode 100644
index 0000000..1f37049
--- /dev/null
+++ b/apps/www/src/components/embeddings/embedding.tsx
@@ -0,0 +1,93 @@
+"use client";
+
+import React, { useState } from "react";
+
+import { Button } from "@acme/ui/button";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+} from "@acme/ui/card";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@acme/ui/tabs";
+
+const HighlightedCode = ({ code }: { code: string }) => (
+
+ {code}
+
+);
+
+export default function Embedding({ website }: { website: string }) {
+ const [showEmbed, setShowEmbed] = useState(true);
+
+ const embedCode = ``;
+ return (
+
+
+
+ Testimonial Embed Demo
+
+ See how to embed testimonials in your website
+
+
+
+
+
+ Preview
+ Code
+
+
+
+
Live Preview
+
+
+ {showEmbed && (
+
+ )}
+
+
+ Embed Code
+
+
+
How to use:
+
+ - Copy the code above
+ -
+ Paste it into your HTML where you want the testimonials to
+ appear
+
+ - Adjust the width and height as needed
+ -
+ Replace 'http://localhost:3001' with your actual domain if
+ different
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/apps/www/src/components/products/app-sidebar.tsx b/apps/www/src/components/products/app-sidebar.tsx
index 8d4e610..24ce1f6 100644
--- a/apps/www/src/components/products/app-sidebar.tsx
+++ b/apps/www/src/components/products/app-sidebar.tsx
@@ -5,12 +5,14 @@ import { usePathname } from "next/navigation";
import {
ArchiveIcon,
ArrowBigLeft,
+ Book,
Calendar,
Edit,
Heart,
Home,
Inbox,
LucideDelete,
+ Pin,
TicketsPlane,
} from "lucide-react";
@@ -75,6 +77,19 @@ const spaceSettings = [
},
];
+const embeddings = [
+ {
+ title: "embed",
+ url: "embed",
+ icon: Pin,
+ },
+ {
+ title: "embed-doc",
+ url: "embed-doc",
+ icon: Book,
+ },
+];
+
export function AppSidebar({ className }: { className?: string }) {
const path = usePathname().split("/");
return (
@@ -114,6 +129,23 @@ export function AppSidebar({ className }: { className?: string }) {
+
+ Embeddings
+
+
+ {embeddings.map((item) => (
+
+
+
+
+ {item.title}
+
+
+
+ ))}
+
+
+
Settings
diff --git a/packages/api/src/types/database-type.ts b/packages/api/src/types/database-type.ts
new file mode 100644
index 0000000..20b5d9b
--- /dev/null
+++ b/packages/api/src/types/database-type.ts
@@ -0,0 +1,20 @@
+import type { organizationTable, testimonialTable } from "@acme/db/schema";
+
+export interface OrganizationTestimonialType {
+ id: string;
+ ownerId: string;
+ website: string;
+ logo: string | null;
+ organizationName: string;
+ createdAt: Date;
+ updatedAt: Date;
+ headerTitle: string;
+ customMessage: string;
+ testimonials: TestimonialType[];
+}
+
+export type OrganizationType = typeof organizationTable.$inferSelect;
+
+export type TestimonialType = typeof testimonialTable.$inferSelect;
+
+export type TestimonialTableType = typeof testimonialTable;
diff --git a/packages/ui/package.json b/packages/ui/package.json
index ad1da57..a368231 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -38,6 +38,7 @@
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slider": "^1.2.1",
"@radix-ui/react-slot": "^1.1.0",
+ "@radix-ui/react-tabs": "^1.1.1",
"@radix-ui/react-tooltip": "^1.1.3",
"class-variance-authority": "^0.7.0",
"next-themes": "^0.3.0",
diff --git a/packages/ui/src/sidebar.tsx b/packages/ui/src/sidebar.tsx
index 6eaa9a0..ed2e494 100644
--- a/packages/ui/src/sidebar.tsx
+++ b/packages/ui/src/sidebar.tsx
@@ -245,7 +245,7 @@ const Sidebar = React.forwardRef<
/>
+>(({ className, ...props }, ref) => (
+
+));
+Table.displayName = "Table";
+
+const TableHeader = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+TableHeader.displayName = "TableHeader";
+
+const TableBody = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+TableBody.displayName = "TableBody";
+
+const TableFooter = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+ tr]:last:border-b-0",
+ className,
+ )}
+ {...props}
+ />
+));
+TableFooter.displayName = "TableFooter";
+
+const TableRow = React.forwardRef<
+ HTMLTableRowElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+TableRow.displayName = "TableRow";
+
+const TableHead = React.forwardRef<
+ HTMLTableCellElement,
+ React.ThHTMLAttributes
+>(({ className, ...props }, ref) => (
+ [role=checkbox]]:translate-y-[2px]",
+ className,
+ )}
+ {...props}
+ />
+));
+TableHead.displayName = "TableHead";
+
+const TableCell = React.forwardRef<
+ HTMLTableCellElement,
+ React.TdHTMLAttributes
+>(({ className, ...props }, ref) => (
+ [role=checkbox]]:translate-y-[2px]",
+ className,
+ )}
+ {...props}
+ />
+));
+TableCell.displayName = "TableCell";
+
+const TableCaption = React.forwardRef<
+ HTMLTableCaptionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+TableCaption.displayName = "TableCaption";
+
+export {
+ Table,
+ TableHeader,
+ TableBody,
+ TableFooter,
+ TableHead,
+ TableRow,
+ TableCell,
+ TableCaption,
+};
diff --git a/packages/ui/src/tabs.tsx b/packages/ui/src/tabs.tsx
new file mode 100644
index 0000000..5d96fc7
--- /dev/null
+++ b/packages/ui/src/tabs.tsx
@@ -0,0 +1,55 @@
+"use client";
+
+import * as React from "react";
+import * as TabsPrimitive from "@radix-ui/react-tabs";
+
+import { cn } from "@acme/ui";
+
+const Tabs = TabsPrimitive.Root;
+
+const TabsList = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsList.displayName = TabsPrimitive.List.displayName;
+
+const TabsTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
+
+const TabsContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsContent.displayName = TabsPrimitive.Content.displayName;
+
+export { Tabs, TabsList, TabsTrigger, TabsContent };
diff --git a/packages/ui/src/theme.tsx b/packages/ui/src/theme.tsx
index 4585c67..d827616 100644
--- a/packages/ui/src/theme.tsx
+++ b/packages/ui/src/theme.tsx
@@ -59,4 +59,4 @@ function ThemeToggle() {
);
}
-export { ThemeProvider, ThemeToggle };
+export { ThemeProvider, ThemeToggle, useTheme };
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 53ce1d4..e6dd48e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -440,6 +440,9 @@ importers:
'@radix-ui/react-slot':
specifier: ^1.1.0
version: 1.1.0(@types/react@18.3.11)(react@18.3.1)
+ '@radix-ui/react-tabs':
+ specifier: ^1.1.1
+ version: 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-tooltip':
specifier: ^1.1.3
version: 1.1.3(@types/react-dom@18.3.1)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -1741,6 +1744,19 @@ packages:
'@types/react':
optional: true
+ '@radix-ui/react-tabs@1.1.1':
+ resolution: {integrity: sha512-3GBUDmP2DvzmtYLMsHmpA1GtR46ZDZ+OreXM/N+kkQJOPIgytFWWTfDQmBQKBvaFS0Vno0FktdbVzN28KGrMdw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-tooltip@1.1.3':
resolution: {integrity: sha512-Z4w1FIS0BqVFI2c1jZvb/uDVJijJjJ2ZMuPV81oVgTZ7g3BZxobplnMVvXtFWgtozdvYJ+MFWtwkM5S2HnAong==}
peerDependencies:
@@ -5524,6 +5540,22 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.11
+ '@radix-ui/react-tabs@1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.0
+ '@radix-ui/react-context': 1.1.1(@types/react@18.3.11)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.0(@types/react@18.3.11)(react@18.3.1)
+ '@radix-ui/react-id': 1.1.0(@types/react@18.3.11)(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.11)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.11
+ '@types/react-dom': 18.3.1
+
'@radix-ui/react-tooltip@1.1.3(@types/react-dom@18.3.1)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.0
| |