From aae0fc06fc8cf41c1a84d1220bd39fff710800d1 Mon Sep 17 00:00:00 2001 From: Hari Nugraha Date: Fri, 9 Jan 2026 10:50:20 +0700 Subject: [PATCH 1/2] feat: remove inference ai --- .../inferenceai/[slug]/components/dubsy.tsx | 37 -- .../[slug]/components/media-pulse.tsx | 68 --- .../[slug]/components/presenton.tsx | 46 -- .../[slug]/components/startgpt.tsx | 46 -- .../inferenceai/[slug]/components/voxa.tsx | 339 ----------- .../(inferenceai)/inferenceai/[slug]/data.tsx | 575 ------------------ .../(inferenceai)/inferenceai/[slug]/home.tsx | 227 ------- .../(inferenceai)/inferenceai/[slug]/page.tsx | 45 -- .../inferenceai/components/chatbot-ui.tsx | 298 --------- .../inferenceai/components/client-wrapper.tsx | 24 - .../inferenceai/components/footer.tsx | 59 -- .../inferenceai/components/nav.tsx | 260 -------- app/[lang]/(inferenceai)/inferenceai/data.tsx | 444 -------------- app/[lang]/(inferenceai)/inferenceai/home.tsx | 371 ----------- .../(inferenceai)/inferenceai/layout.tsx | 27 - app/[lang]/(inferenceai)/inferenceai/page.tsx | 38 -- bun.lock | 19 +- e2e/navigation.spec.ts | 2 +- locales/en/dubsy.json | 65 -- locales/en/inferenceai.json | 100 --- locales/en/media-pulse.json | 70 --- locales/en/presenton.json | 66 -- locales/en/start-gpt.json | 61 -- locales/en/voxa.json | 79 --- locales/id/dubsy.json | 65 -- locales/id/inferenceai.json | 99 --- locales/id/media-pulse.json | 70 --- locales/id/presenton.json | 66 -- locales/id/start-gpt.json | 61 -- locales/id/voxa.json | 79 --- package.json | 8 +- 31 files changed, 13 insertions(+), 3801 deletions(-) delete mode 100644 app/[lang]/(inferenceai)/inferenceai/[slug]/components/dubsy.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/[slug]/components/media-pulse.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/[slug]/components/presenton.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/[slug]/components/startgpt.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/[slug]/components/voxa.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/[slug]/data.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/[slug]/home.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/[slug]/page.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/components/chatbot-ui.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/components/client-wrapper.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/components/footer.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/components/nav.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/data.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/home.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/layout.tsx delete mode 100644 app/[lang]/(inferenceai)/inferenceai/page.tsx delete mode 100644 locales/en/dubsy.json delete mode 100644 locales/en/inferenceai.json delete mode 100644 locales/en/presenton.json delete mode 100644 locales/en/voxa.json delete mode 100644 locales/id/dubsy.json delete mode 100644 locales/id/inferenceai.json delete mode 100644 locales/id/presenton.json delete mode 100644 locales/id/voxa.json diff --git a/app/[lang]/(inferenceai)/inferenceai/[slug]/components/dubsy.tsx b/app/[lang]/(inferenceai)/inferenceai/[slug]/components/dubsy.tsx deleted file mode 100644 index 203cf2fe..00000000 --- a/app/[lang]/(inferenceai)/inferenceai/[slug]/components/dubsy.tsx +++ /dev/null @@ -1,37 +0,0 @@ -export default function Dubsy() { - return ( -
-
- {/* Before Video */} -
-
- Before -
-
-
-
- - {/* After Video */} -
-
- After -
-
-
-
-
-
- ); -} diff --git a/app/[lang]/(inferenceai)/inferenceai/[slug]/components/media-pulse.tsx b/app/[lang]/(inferenceai)/inferenceai/[slug]/components/media-pulse.tsx deleted file mode 100644 index 3b107ece..00000000 --- a/app/[lang]/(inferenceai)/inferenceai/[slug]/components/media-pulse.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import rehypeStringify from "rehype-stringify"; -import remarkGfm from "remark-gfm"; -import remarkParse from "remark-parse"; -import remarkRehype from "remark-rehype"; -import { unified } from "unified"; -import { visit } from "unist-util-visit"; -import { Card, CardContent } from "@/components/ui/card"; - -type NewsSummary = { - summary: string; -}; - -const API_URL = "https://chat.hyperjump.tech/media-pulse/v1/news-summaries"; - -export async function MediaPulse() { - const response = await fetch(API_URL); - if (!response.ok || response.status < 200 || response.status > 299) { - return null; - } - - const newsSummaries: NewsSummary[] = await response.json(); - const htmlNewsSummaries = await Promise.all( - newsSummaries.map(async ({ summary }) => - String( - await unified() - .use(remarkParse) - .use(remarkGfm) - .use(remarkCompleteLinks) - .use(remarkRehype) - .use(rehypeStringify) - .process(summary) - ) - ) - ); - - return ( -
- {htmlNewsSummaries.map((summary, index) => ( - - -
-
-
- - - ))} -
- ); -} - -function remarkCompleteLinks() { - return (tree: any) => { - visit(tree, "link", (node) => { - try { - if (!new URL(node.url).protocol) { - node.url = `https://${node.url}`; - } - } catch { - // not a valid absolute URL; attempt with https:// - node.url = `https://${node.url}`; - } - }); - }; -} diff --git a/app/[lang]/(inferenceai)/inferenceai/[slug]/components/presenton.tsx b/app/[lang]/(inferenceai)/inferenceai/[slug]/components/presenton.tsx deleted file mode 100644 index e5b99393..00000000 --- a/app/[lang]/(inferenceai)/inferenceai/[slug]/components/presenton.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { Button } from "@/components/ui/button"; -import { - inferenceaiHeroLabelDemoButton, - inferenceaiHeroTextDemo, - inferenceaiHeroUsername, - inferenceaiHeroPassword -} from "@/locales/.generated/server"; -import type { SupportedLanguage } from "@/locales/.generated/types"; -import Link from "next/link"; - -export default function Presenton({ - demoUrl, - lang, - slug, - username, - password -}: { - demoUrl: string; - lang: SupportedLanguage; - slug: string; - username: string; - password: string; -}) { - return ( - <> - -
-
{inferenceaiHeroTextDemo(lang)}
- - {inferenceaiHeroUsername(lang)}: {username}  | {" "} - {inferenceaiHeroPassword(lang)}: {password} - -
- - ); -} diff --git a/app/[lang]/(inferenceai)/inferenceai/[slug]/components/startgpt.tsx b/app/[lang]/(inferenceai)/inferenceai/[slug]/components/startgpt.tsx deleted file mode 100644 index 1b438465..00000000 --- a/app/[lang]/(inferenceai)/inferenceai/[slug]/components/startgpt.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { Button } from "@/components/ui/button"; -import { - inferenceaiHeroLabelDemoButton, - inferenceaiHeroTextDemo, - inferenceaiHeroUsername, - inferenceaiHeroPassword -} from "@/locales/.generated/server"; -import Link from "next/link"; -import type { SupportedLanguage } from "@/locales/.generated/types"; - -export default function StartGPT({ - demoUrl, - lang, - slug, - username, - password -}: { - demoUrl: string; - lang: SupportedLanguage; - slug: string; - username: string; - password: string; -}) { - return ( - <> - -
-
{inferenceaiHeroTextDemo(lang)}
- - {inferenceaiHeroUsername(lang)}: {username}  | {" "} - {inferenceaiHeroPassword(lang)}: {password} - -
- - ); -} diff --git a/app/[lang]/(inferenceai)/inferenceai/[slug]/components/voxa.tsx b/app/[lang]/(inferenceai)/inferenceai/[slug]/components/voxa.tsx deleted file mode 100644 index 58b45cb1..00000000 --- a/app/[lang]/(inferenceai)/inferenceai/[slug]/components/voxa.tsx +++ /dev/null @@ -1,339 +0,0 @@ -"use client"; - -import { Button } from "@/components/ui/button"; -import { Card, CardContent, CardHeader } from "@/components/ui/card"; -import { FileText, Mic, Pause, Phone, Play } from "lucide-react"; -import { useEffect, useRef, useState } from "react"; - -export default function Voxa() { - const audioRef = useRef(null); - const [isPlaying, setIsPlaying] = useState(false); - const progressBarRef = useRef(null); - const [currentTime, setCurrentTime] = useState(0); - const [duration, setDuration] = useState(0); - const [hoverTime, setHoverTime] = useState(null); - const [isHovering, setIsHovering] = useState(false); - const [isAudioLoaded, setIsAudioLoaded] = useState(false); - - const handlePlayPause = () => { - if (audioRef.current) { - if (audioRef.current.paused) { - audioRef.current.play(); - } else { - audioRef.current.pause(); - } - } - }; - - const handleSeek = (e: React.MouseEvent) => { - if (audioRef.current && duration > 0) { - const rect = e.currentTarget.getBoundingClientRect(); - const clickX = e.clientX - rect.left; - const percentage = clickX / rect.width; - const newTime = percentage * duration; - audioRef.current.currentTime = newTime; - setCurrentTime(newTime); - } - }; - - const handleProgressHover = (e: React.MouseEvent) => { - if (duration > 0) { - const rect = e.currentTarget.getBoundingClientRect(); - const clickX = e.clientX - rect.left; - const percentage = clickX / rect.width; - const hoverTimeValue = percentage * duration; - setHoverTime(hoverTimeValue); - setIsHovering(true); - } - }; - - const handleProgressLeave = () => { - setIsHovering(false); - setHoverTime(null); - }; - - const handleRefreshDuration = () => { - if (audioRef.current) { - audioRef.current.load(); - setTimeout(() => { - if (audioRef.current?.duration && !isNaN(audioRef.current.duration)) { - setDuration(audioRef.current.duration); - setIsAudioLoaded(true); - } - }, 100); - } - }; - - const formatTime = (seconds: number) => { - if (isNaN(seconds)) return "0:00"; - const minutes = Math.floor(seconds / 60); - const remainingSeconds = Math.floor(seconds % 60); - return `${minutes}:${remainingSeconds.toString().padStart(2, "0")}`; - }; - - useEffect(() => { - const audio = audioRef.current; - if (!audio) return; - - const handlePlay = () => setIsPlaying(true); - const handlePause = () => setIsPlaying(false); - const handleTimeUpdate = () => setCurrentTime(audio.currentTime); - const handleLoadedMetadata = () => { - if (audio.duration && !isNaN(audio.duration)) { - setDuration(audio.duration); - setIsAudioLoaded(true); - } - }; - const handleCanPlay = () => { - if (audio.duration && !isNaN(audio.duration)) { - setDuration(audio.duration); - setIsAudioLoaded(true); - } - }; - const handleLoadedData = () => { - if (audio.duration && !isNaN(audio.duration)) { - setDuration(audio.duration); - setIsAudioLoaded(true); - } - }; - const handleError = (e: Event) => { - setIsAudioLoaded(false); - }; - const handleEnded = () => setIsPlaying(false); - - // Force load the audio - audio.load(); - - // Also try to access duration directly after a short delay - setTimeout(() => { - if (audio.duration && !isNaN(audio.duration) && audio.duration > 0) { - setDuration(audio.duration); - setIsAudioLoaded(true); - } - }, 500); - - audio.addEventListener("play", handlePlay); - audio.addEventListener("pause", handlePause); - audio.addEventListener("timeupdate", handleTimeUpdate); - audio.addEventListener("loadedmetadata", handleLoadedMetadata); - audio.addEventListener("canplay", handleCanPlay); - audio.addEventListener("loadeddata", handleLoadedData); - audio.addEventListener("error", handleError); - audio.addEventListener("ended", handleEnded); - - // Check if duration is already available - if (audio.duration && !isNaN(audio.duration)) { - setDuration(audio.duration); - setIsAudioLoaded(true); - } - - // Fallback: check duration periodically - const checkDuration = () => { - if (audio.duration && !isNaN(audio.duration) && audio.duration > 0) { - setDuration(audio.duration); - setIsAudioLoaded(true); - return true; - } - return false; - }; - - const intervalId = setInterval(() => { - if (checkDuration()) { - clearInterval(intervalId); - } - }, 100); - - // Clean up interval and event listeners - return () => { - clearInterval(intervalId); - audio.removeEventListener("play", handlePlay); - audio.removeEventListener("pause", handlePause); - audio.removeEventListener("timeupdate", handleTimeUpdate); - audio.removeEventListener("loadedmetadata", handleLoadedMetadata); - audio.removeEventListener("canplay", handleCanPlay); - audio.removeEventListener("loadeddata", handleLoadedData); - audio.removeEventListener("error", handleError); - audio.removeEventListener("ended", handleEnded); - }; - }, []); - - return ( -
- {/* Timeline dotted line background */} -
- {/* Vertical line for mobile/tablet, horizontal for desktop */} -
- - {/* Step 1: Script & Phone */} - - -
- -
-

Your Input

-
- -
-
-

- Phone Number: -

-
-

+1 (***) ***-1234

-
-
- -
-

Your Script:

-
-

- Hi there, if I could cut your team's busywork by 30% - with AI this quarter, would you want to see how? -

-

- We at Inference AI, we help automate repetitive workflows so - your team can focus on high-value tasks. -

-

- If you are interested, send us an email to - solution@hyperjump.tech. -

-

Thank you for your time!

-
-
-
-
-
- - {/* Step 2: VOXA */} - - -
- -
-

VOXA

-
- -
-

Processing

-
-
-
-
-
-

Converting script to natural AI voice

-
- - - - {/* Step 3: Result */} - - -
- -
-

Result

-
- -
-

- The number you inputted will receive a call: -

- - {/* Audio Player Mockup */} -
-
- -
-
- {formatTime(currentTime)} - / - - {isAudioLoaded ? formatTime(duration) : "Loading..."} - -
- {!isAudioLoaded && ( -
- - Loading audio... (Duration: {duration}s, Loaded:{" "} - {isAudioLoaded ? "Yes" : "No"}) - - -
- )} -
-
0 ? (currentTime / duration) * 100 : 0}%` - }} - /> -
0 ? (currentTime / duration) * 100 : 0}%` - }} - /> - {isHovering && hoverTime !== null && ( - <> -
-
- {formatTime(hoverTime)} -
- - )} -
-
-
-
- -

- AI voice calls your prospect automatically -

-
- - -
-
- ); -} diff --git a/app/[lang]/(inferenceai)/inferenceai/[slug]/data.tsx b/app/[lang]/(inferenceai)/inferenceai/[slug]/data.tsx deleted file mode 100644 index 44014431..00000000 --- a/app/[lang]/(inferenceai)/inferenceai/[slug]/data.tsx +++ /dev/null @@ -1,575 +0,0 @@ -import type { ReactNode } from "react"; - -import type { SupportedLanguage } from "@/locales/.generated/types"; -import { - presentonKeyFeaturesFeatures0Title, - presentonKeyFeaturesFeatures1Title, - presentonKeyFeaturesFeatures2Title, - presentonKeyFeaturesFeatures3Title, - presentonKeyFeaturesFeatures0Text, - presentonKeyFeaturesFeatures1Text, - presentonKeyFeaturesFeatures2Text, - presentonKeyFeaturesFeatures3Text, - presentonHowItWorksSteps0Title, - presentonHowItWorksSteps1Title, - presentonHowItWorksSteps2Title, - presentonHowItWorksSteps3Title, - presentonHowItWorksSteps0Text, - presentonHowItWorksSteps1Text, - presentonHowItWorksSteps2Text, - presentonHowItWorksSteps3Text, - presentonWhatIsIncludedItems0, - presentonWhatIsIncludedItems1, - presentonWhatIsIncludedItems2, - presentonFaq0Question, - presentonFaq1Question, - presentonFaq2Question, - presentonFaq0Answer, - presentonFaq1Answer, - presentonFaq2Answer, - mediaPulseKeyFeaturesFeatures0Title, - mediaPulseKeyFeaturesFeatures1Title, - mediaPulseKeyFeaturesFeatures2Title, - mediaPulseKeyFeaturesFeatures3Title, - mediaPulseKeyFeaturesFeatures0Text, - mediaPulseKeyFeaturesFeatures1Text, - mediaPulseKeyFeaturesFeatures2Text, - mediaPulseKeyFeaturesFeatures3Text, - mediaPulseHowItWorksSteps0Title, - mediaPulseHowItWorksSteps1Title, - mediaPulseHowItWorksSteps2Title, - mediaPulseHowItWorksSteps3Title, - mediaPulseHowItWorksSteps0Text, - mediaPulseHowItWorksSteps1Text, - mediaPulseHowItWorksSteps2Text, - mediaPulseHowItWorksSteps3Text, - mediaPulseWhatIsIncludedItems0Title, - mediaPulseWhatIsIncludedItems1Title, - mediaPulseWhatIsIncludedItems0Text, - mediaPulseWhatIsIncludedItems1Text, - mediaPulseFaq0Question, - mediaPulseFaq1Question, - mediaPulseFaq2Question, - mediaPulseFaq3Question, - mediaPulseFaq4Question, - mediaPulseFaq0Answer, - mediaPulseFaq1Answer, - mediaPulseFaq2Answer, - mediaPulseFaq3Answer, - mediaPulseFaq4Answer, - startGptKeyFeaturesFeatures0Title, - startGptKeyFeaturesFeatures1Title, - startGptKeyFeaturesFeatures2Title, - startGptKeyFeaturesFeatures3Title, - startGptKeyFeaturesFeatures0Text, - startGptKeyFeaturesFeatures1Text, - startGptKeyFeaturesFeatures2Text, - startGptKeyFeaturesFeatures3Text, - startGptHowItWorksSteps0Title, - startGptHowItWorksSteps1Title, - startGptHowItWorksSteps2Title, - startGptHowItWorksSteps3Title, - startGptHowItWorksSteps0Text, - startGptHowItWorksSteps1Text, - startGptHowItWorksSteps2Text, - startGptHowItWorksSteps3Text, - startGptFaq0Question, - startGptFaq1Question, - startGptFaq2Question, - startGptFaq3Question, - startGptFaq0Answer, - startGptFaq1Answer, - startGptFaq2Answer, - startGptFaq3Answer, - startGptFaq4Question, - startGptFaq4Answer, - startGptHowItWorksSteps4Title, - startGptHowItWorksSteps4Text, - voxaKeyFeaturesFeatures0Title, - voxaKeyFeaturesFeatures1Title, - voxaKeyFeaturesFeatures2Title, - voxaKeyFeaturesFeatures3Title, - voxaKeyFeaturesFeatures0Text, - voxaKeyFeaturesFeatures1Text, - voxaKeyFeaturesFeatures2Text, - voxaKeyFeaturesFeatures3Text, - voxaHowItWorksSteps0Title, - voxaHowItWorksSteps1Title, - voxaHowItWorksSteps2Title, - voxaHowItWorksSteps3Title, - voxaHowItWorksSteps0Text, - voxaHowItWorksSteps1Text, - voxaHowItWorksSteps2Text, - voxaHowItWorksSteps3Text, - voxaWhatIsIncludedItems0, - voxaWhatIsIncludedItems1, - voxaWhatIsIncludedItems2, - voxaFaq0Question, - voxaFaq1Question, - voxaFaq2Question, - voxaFaq0Answer, - voxaFaq1Answer, - voxaFaq2Answer, - voxaWhatIsIncludedItems3, - voxaFaq3Question, - voxaFaq3Answer, - voxaFaq4Question, - voxaFaq4Answer, - voxaFaq5Question, - voxaFaq5Answer, - dubsyHowItWorksSteps0Title, - dubsyHowItWorksSteps2Title, - dubsyHowItWorksSteps3Title, - dubsyHowItWorksSteps1Text, - dubsyHowItWorksSteps1Title, - dubsyHowItWorksSteps0Text, - dubsyWhatIsIncludedItems0, - dubsyWhatIsIncludedItems1, - dubsyFaq0Question, - dubsyFaq0Answer, - dubsyFaq1Question, - dubsyFaq1Answer, - dubsyFaq2Question, - dubsyFaq2Answer, - dubsyKeyFeaturesFeatures0Text, - dubsyKeyFeaturesFeatures0Title, - dubsyKeyFeaturesFeatures1Text, - dubsyKeyFeaturesFeatures1Title, - dubsyKeyFeaturesFeatures2Title, - dubsyKeyFeaturesFeatures2Text -} from "@/locales/.generated/server"; -import { - ChatBubbleIcon, - ClockIcon, - FileTextIcon, - LayersIcon, - Link2Icon, - DashboardIcon -} from "@radix-ui/react-icons"; -import { Users } from "lucide-react"; - -export type WhatIsIncluded = { - icon: ReactNode; - title: string; - text?: string; -}; - -type Faq = { - answer: string; - question: string; -}; - -export const getKeyFeaturesPresenton = (lang: SupportedLanguage) => { - return [ - { - title: presentonKeyFeaturesFeatures0Title(lang), - description: presentonKeyFeaturesFeatures0Text(lang), - icon: - }, - { - title: presentonKeyFeaturesFeatures1Title(lang), - description: presentonKeyFeaturesFeatures1Text(lang), - icon: - }, - { - title: presentonKeyFeaturesFeatures2Title(lang), - description: presentonKeyFeaturesFeatures2Text(lang), - icon: - }, - { - title: presentonKeyFeaturesFeatures3Title(lang), - description: presentonKeyFeaturesFeatures3Text(lang) - } - ]; -}; - -export const getHowItWorksPresenton = (lang: SupportedLanguage) => { - return [ - { - title: presentonHowItWorksSteps0Title(lang), - description: presentonHowItWorksSteps0Text(lang) - }, - { - title: presentonHowItWorksSteps1Title(lang), - description: presentonHowItWorksSteps1Text(lang) - }, - { - title: presentonHowItWorksSteps2Title(lang), - description: presentonHowItWorksSteps2Text(lang) - }, - { - title: presentonHowItWorksSteps3Title(lang), - description: presentonHowItWorksSteps3Text(lang) - } - ]; -}; - -export const getWhatIsIncludedPresenton = ( - lang: SupportedLanguage -): WhatIsIncluded[] => { - return [ - { - title: presentonWhatIsIncludedItems0(lang), - icon: - }, - { - title: presentonWhatIsIncludedItems1(lang), - icon: - }, - { - title: presentonWhatIsIncludedItems2(lang), - icon: - } - ]; -}; - -export const getFaqsPresenton = (lang: SupportedLanguage) => { - return [ - { - question: presentonFaq0Question(lang), - answer: presentonFaq0Answer(lang) - }, - { - question: presentonFaq1Question(lang), - answer: presentonFaq1Answer(lang) - }, - { - question: presentonFaq2Question(lang), - answer: presentonFaq2Answer(lang) - } - ]; -}; - -export const getKeyFeaturesMediaPulse = (lang: SupportedLanguage) => { - const data = [ - { - title: mediaPulseKeyFeaturesFeatures0Title(lang), - description: mediaPulseKeyFeaturesFeatures0Text(lang), - icon: - }, - { - title: mediaPulseKeyFeaturesFeatures1Title(lang), - description: mediaPulseKeyFeaturesFeatures1Text(lang), - icon: - }, - { - title: mediaPulseKeyFeaturesFeatures2Title(lang), - description: mediaPulseKeyFeaturesFeatures2Text(lang), - icon: - }, - { - title: mediaPulseKeyFeaturesFeatures3Title(lang), - description: mediaPulseKeyFeaturesFeatures3Text(lang), - icon: - } - ]; - - return data; -}; - -export const getHowItWorksMediaPulse = (lang: SupportedLanguage) => { - const data = [ - { - title: mediaPulseHowItWorksSteps0Title(lang), - description: mediaPulseHowItWorksSteps0Text(lang) - }, - { - title: mediaPulseHowItWorksSteps1Title(lang), - description: mediaPulseHowItWorksSteps1Text(lang) - }, - { - title: mediaPulseHowItWorksSteps2Title(lang), - description: mediaPulseHowItWorksSteps2Text(lang) - }, - { - title: mediaPulseHowItWorksSteps3Title(lang), - description: mediaPulseHowItWorksSteps3Text(lang) - } - ]; - - return data; -}; - -export const getWhatIsIncludedMediaPulse = ( - lang: SupportedLanguage -): WhatIsIncluded[] => { - return [ - { - title: mediaPulseWhatIsIncludedItems0Title(lang), - text: mediaPulseWhatIsIncludedItems0Text(lang), - icon: - }, - { - title: mediaPulseWhatIsIncludedItems1Title(lang), - text: mediaPulseWhatIsIncludedItems1Text(lang), - icon: - } - ]; -}; - -export const getFaqsMediaPulse = (lang: SupportedLanguage): Faq[] => { - return [ - { - question: mediaPulseFaq0Question(lang), - answer: mediaPulseFaq0Answer(lang) - }, - { - question: mediaPulseFaq1Question(lang), - answer: mediaPulseFaq1Answer(lang) - }, - { - question: mediaPulseFaq2Question(lang), - answer: mediaPulseFaq2Answer(lang) - }, - { - question: mediaPulseFaq3Question(lang), - answer: mediaPulseFaq3Answer(lang) - }, - { - question: mediaPulseFaq4Question(lang), - answer: mediaPulseFaq4Answer(lang) - } - ]; -}; - -export const getKeyFeaturesStartGPT = (lang: SupportedLanguage) => { - return [ - { - title: startGptKeyFeaturesFeatures0Title(lang), - description: startGptKeyFeaturesFeatures0Text(lang), - icon: - }, - { - title: startGptKeyFeaturesFeatures1Title(lang), - description: startGptKeyFeaturesFeatures1Text(lang), - icon: - }, - { - title: startGptKeyFeaturesFeatures2Title(lang), - description: startGptKeyFeaturesFeatures2Text(lang), - icon: - }, - { - title: startGptKeyFeaturesFeatures3Title(lang), - description: startGptKeyFeaturesFeatures3Text(lang) - } - ]; -}; - -export const getKeyFeaturesVoxa = (lang: SupportedLanguage) => { - return [ - { - title: voxaKeyFeaturesFeatures0Title(lang), - description: voxaKeyFeaturesFeatures0Text(lang), - icon: - }, - { - title: voxaKeyFeaturesFeatures1Title(lang), - description: voxaKeyFeaturesFeatures1Text(lang), - icon: - }, - { - title: voxaKeyFeaturesFeatures2Title(lang), - description: voxaKeyFeaturesFeatures2Text(lang), - icon: - }, - { - title: voxaKeyFeaturesFeatures3Title(lang), - description: voxaKeyFeaturesFeatures3Text(lang), - icon: - } - ]; -}; - -export const getHowItWorksStartGPT = (lang: SupportedLanguage) => { - return [ - { - title: startGptHowItWorksSteps0Title(lang), - description: startGptHowItWorksSteps0Text(lang) - }, - { - title: startGptHowItWorksSteps1Title(lang), - description: startGptHowItWorksSteps1Text(lang) - }, - { - title: startGptHowItWorksSteps2Title(lang), - description: startGptHowItWorksSteps2Text(lang) - }, - { - title: startGptHowItWorksSteps3Title(lang), - description: startGptHowItWorksSteps3Text(lang) - }, - { - title: startGptHowItWorksSteps4Title(lang), - description: startGptHowItWorksSteps4Text(lang) - } - ]; -}; - -export const getFaqsStartGPT = (lang: SupportedLanguage) => { - return [ - { - question: startGptFaq0Question(lang), - answer: startGptFaq0Answer(lang) - }, - { - question: startGptFaq1Question(lang), - answer: startGptFaq1Answer(lang) - }, - { - question: startGptFaq2Question(lang), - answer: startGptFaq2Answer(lang) - }, - { - question: startGptFaq3Question(lang), - answer: startGptFaq3Answer(lang) - }, - { - question: startGptFaq4Question(lang), - answer: startGptFaq4Answer(lang) - } - ]; -}; - -export const getHowItWorksVoxa = (lang: SupportedLanguage) => { - return [ - { - title: voxaHowItWorksSteps0Title(lang), - description: voxaHowItWorksSteps0Text(lang) - }, - { - title: voxaHowItWorksSteps1Title(lang), - description: voxaHowItWorksSteps1Text(lang) - }, - { - title: voxaHowItWorksSteps2Title(lang), - description: voxaHowItWorksSteps2Text(lang) - }, - { - title: voxaHowItWorksSteps3Title(lang), - description: voxaHowItWorksSteps3Text(lang) - } - ]; -}; - -export const getWhatIsIncludedVoxa = ( - lang: SupportedLanguage -): WhatIsIncluded[] => { - return [ - { - title: voxaWhatIsIncludedItems0(lang), - icon: - }, - { - title: voxaWhatIsIncludedItems1(lang), - icon: - }, - { - title: voxaWhatIsIncludedItems2(lang), - icon: - }, - { - title: voxaWhatIsIncludedItems3(lang), - icon: - } - ]; -}; - -export const getFaqsVoxa = (lang: SupportedLanguage) => { - return [ - { - question: voxaFaq0Question(lang), - answer: voxaFaq0Answer(lang) - }, - { - question: voxaFaq1Question(lang), - answer: voxaFaq1Answer(lang) - }, - { - question: voxaFaq2Question(lang), - answer: voxaFaq2Answer(lang) - }, - { - question: voxaFaq3Question(lang), - answer: voxaFaq3Answer(lang) - }, - { - question: voxaFaq4Question(lang), - answer: voxaFaq4Answer(lang) - }, - { - question: voxaFaq5Question(lang), - answer: voxaFaq5Answer(lang) - } - ]; -}; - -export const getHowItWorksDubsy = (lang: SupportedLanguage) => { - return [ - { - title: dubsyHowItWorksSteps0Title(lang), - description: dubsyHowItWorksSteps0Text(lang) - }, - { - title: dubsyHowItWorksSteps1Title(lang), - description: dubsyHowItWorksSteps1Text(lang) - }, - { - title: dubsyHowItWorksSteps2Title(lang), - description: voxaHowItWorksSteps2Text(lang) - }, - { - title: dubsyHowItWorksSteps3Title(lang), - description: voxaHowItWorksSteps3Text(lang) - } - ]; -}; - -export const getWhatIsIncludedDubsy = ( - lang: SupportedLanguage -): WhatIsIncluded[] => { - return [ - { - title: dubsyWhatIsIncludedItems0(lang), - icon: - }, - { - title: dubsyWhatIsIncludedItems1(lang), - icon: - } - ]; -}; - -export const getFaqsDubsy = (lang: SupportedLanguage) => { - return [ - { - question: dubsyFaq0Question(lang), - answer: dubsyFaq0Answer(lang) - }, - { - question: dubsyFaq1Question(lang), - answer: dubsyFaq1Answer(lang) - }, - { - question: dubsyFaq2Question(lang), - answer: dubsyFaq2Answer(lang) - } - ]; -}; - -export const getKeyFeaturesDubsy = (lang: SupportedLanguage) => { - return [ - { - title: dubsyKeyFeaturesFeatures0Title(lang), - description: dubsyKeyFeaturesFeatures0Text(lang) - }, - { - title: dubsyKeyFeaturesFeatures1Title(lang), - description: dubsyKeyFeaturesFeatures1Text(lang) - }, - { - title: dubsyKeyFeaturesFeatures2Title(lang), - description: dubsyKeyFeaturesFeatures2Text(lang) - } - ]; -}; diff --git a/app/[lang]/(inferenceai)/inferenceai/[slug]/home.tsx b/app/[lang]/(inferenceai)/inferenceai/[slug]/home.tsx deleted file mode 100644 index 2da5afad..00000000 --- a/app/[lang]/(inferenceai)/inferenceai/[slug]/home.tsx +++ /dev/null @@ -1,227 +0,0 @@ -"use client"; - -import { motion } from "framer-motion"; -import Image from "next/image"; - -import { - GridItems, - GridItemsContainerBlack, - GridItemsTitleBlack -} from "@/app/components/grid-items"; -import { - Accordion, - AccordionContent, - AccordionItem, - AccordionTrigger -} from "@/components/ui/accordion"; -import { Card, CardContent, CardHeader } from "@/components/ui/card"; -import { cn } from "@/lib/utils"; -import type { SupportedLanguage } from "@/locales/.generated/types"; -import { CaseStudy } from "../data"; - -type HeroProps = { caseStudy: CaseStudy }; - -export function Hero({ caseStudy: { title, demo, description } }: HeroProps) { - return ( -
- - Hero Background - - - {/* Overlay */} -
-
- -

- {title} -

- - - {description} - -
- - {demo} - -
- - - Banner Bottom - -
- -
- ); -} - -export function KeyFeatures({ - caseStudy: { keyFeatures, keyFeaturesHeading }, - lang -}: { lang: SupportedLanguage } & HeroProps) { - return ( - - -
- - - ); -} - -export function HowItWorks({ - caseStudy: { howItWorks, howItWorksHeading } -}: HeroProps) { - return ( -
-
-
- -
- {howItWorks.map(({ description, title }) => ( - - -

- {title} -

-

{description}

-
-
- ))} -
-
-
-
- ); -} - -export function WhatIsIncluded({ - caseStudy: { whatsIncluded, whatsIncludedHeading } -}: HeroProps) { - return ( - - -
-
- {whatsIncluded.map(({ icon, title, text }) => ( - -
- {icon} -

- {title} -

-

- {text} -

- - ))} -
- - ); -} - -export function Faqs({ caseStudy: { faqDesc, faqHeading, faqs } }: HeroProps) { - return ( -
-
-
- -
- - - {faqs.map(({ answer, question }) => ( - - - - - {question} - - - - - - - - ))} - - -
-
-
- ); -} diff --git a/app/[lang]/(inferenceai)/inferenceai/[slug]/page.tsx b/app/[lang]/(inferenceai)/inferenceai/[slug]/page.tsx deleted file mode 100644 index 3884e9a6..00000000 --- a/app/[lang]/(inferenceai)/inferenceai/[slug]/page.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { notFound } from "next/navigation"; - -import { - type SupportedLanguage, - supportedLanguages -} from "@/locales/.generated/types"; - -import { caseStudyBy, getCaseStudies } from "../data"; -import { Faqs, Hero, HowItWorks, KeyFeatures, WhatIsIncluded } from "./home"; - -type Params = { lang: SupportedLanguage; slug: string }; - -type CaseStudyProps = { - params: Params; -}; - -export async function generateStaticParams(): Promise { - return supportedLanguages.reduce((acc, lang) => { - return [ - ...acc, - ...getCaseStudies(lang).map(({ slug }) => ({ slug, lang })) - ]; - }, []); -} - -export default async function CaseStudy({ params }: CaseStudyProps) { - const { lang, slug } = params; - const caseStudy = caseStudyBy(slug, lang); - - if (!caseStudy) { - notFound(); - } - - return ( - <> - - - - {(caseStudy.whatsIncluded ?? []).length > 0 && ( - - )} - - - ); -} diff --git a/app/[lang]/(inferenceai)/inferenceai/components/chatbot-ui.tsx b/app/[lang]/(inferenceai)/inferenceai/components/chatbot-ui.tsx deleted file mode 100644 index 1af10c42..00000000 --- a/app/[lang]/(inferenceai)/inferenceai/components/chatbot-ui.tsx +++ /dev/null @@ -1,298 +0,0 @@ -"use client"; - -import { Button } from "@/components/ui/button"; -import { Separator } from "@/components/ui/separator"; -import Image from "next/image"; -import { useEffect, useRef, useState } from "react"; -import { toast } from "sonner"; - -// Types -type TMessageResponse = { - messages: TMessage[]; - messageCount: number; -}; - -type TMessage = { - ai: string; - human: string; -}; - -// Constants -const DEFAULT_MESSAGES = [ - { id: 1, text: "What services do you offer?" }, - { id: 2, text: "Show me examples of past projects" }, - { id: 3, text: "Schedule a free consultation" } -]; - -// Functions -// APIs -const fetchPreviousMessages = async ( - sessionId: string -): Promise => { - const url = new URL( - `${String(process.env.NEXT_PUBLIC_INFERENCEAI_GET_CHATS_WEBHOOK)}/${sessionId}` - ); - url.searchParams.set("outputType", "html"); - - const response = await fetch(url); - if (!response.ok) { - return { - messages: [], - messageCount: 0 - }; - } - - const data = await response.json(); - return data; -}; - -const fetchAsk = async (payload: { - chatInput: string; - sessionId: string; -}): Promise<{ output: string }> => { - const { chatInput, sessionId } = payload; - const url = String(process.env.NEXT_PUBLIC_INFERENCEAI_POST_CHATS_WEBHOOK); - const response = await fetch(url, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - chatInput, - sessionId, - outputType: "html" - }) - }); - - if (!response.ok) { - return { - output: "Failed to ask question" - }; - } - - const data = await response.json(); - return data; -}; - -// Cookies -function setCookie(cname: string, cvalue: string, exdays: number) { - const d = new Date(); - d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000); // Expiry days * 24 hours * 60 minutes * 60 seconds * 1000 milliseconds - let expires = "expires=" + d.toUTCString(); - document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; -} - -function getCookie(cname: string) { - let name = cname + "="; - let ca = document.cookie.split(";"); - for (let i = 0; i < ca.length; i++) { - let c = ca[i]; - while (c.charAt(0) == " ") { - c = c.substring(1); - } - if (c.indexOf(name) == 0) { - return c.substring(name.length, c.length); - } - } - return ""; -} - -// Main component -export default function InferenceAIAgent() { - const [sessionId, setSessionId] = useState(undefined); - const [messages, setMessages] = useState([]); - const [text, setText] = useState(""); - const [isSubmitting, setIsSubmitting] = useState(false); - - // UI Refs - const inputRef = useRef(null); - const chatContainerRef = useRef(null); - - // Function to scroll to bottom of chat window - const scrollToBottom = () => { - chatContainerRef.current?.scrollTo({ - top: chatContainerRef.current.scrollHeight, - behavior: "smooth" - }); - }; - - // Effect to get session ID from cookie or generate a new one - useEffect(() => { - if (typeof document !== "undefined") { - // Get session ID from cookie - const sessionIdFromCookie = getCookie("INFERENCE_AI_SESSIONID"); - - // If there is a session ID in the cookie, set it from Cookie - if (sessionIdFromCookie) { - setSessionId(sessionIdFromCookie); - } else { - // If not, generate a new session ID - const newSessionId = crypto.randomUUID(); - setSessionId(newSessionId); - setCookie("INFERENCE_AI_SESSIONID", newSessionId, 3); - } - } - }, []); - - // Effect to fetch previous messages - useEffect(() => { - // If there is a session ID, fetch the previous messages - if (sessionId !== undefined) { - setIsSubmitting(true); - // Fetch previous messages - fetchPreviousMessages(sessionId) - .then((response) => { - setMessages(response.messages); - }) - .catch(() => { - setMessages([]); - }) - .finally(() => { - setIsSubmitting(false); - }); - } - }, [sessionId]); - - // Effect to scroll to bottom of chat window on updated messages - useEffect(() => { - if (!chatContainerRef.current) return; - - scrollToBottom(); - }, [messages]); - - // Function to handle form submission - const handleSubmit = async (text: string) => { - if (!text.length || !inputRef.current) return; - - // Set chat input and clear input field - const chatInput = text.trim(); - setText(""); - inputRef.current.value = ""; - - setIsSubmitting(true); - try { - const prevMessages = messages; - const newMessages = [...prevMessages, { human: chatInput, ai: "" }]; - setMessages(newMessages); - const { output } = await fetchAsk({ - chatInput, - sessionId: sessionId as string - }); - - const newMessagesFromAI = [ - ...prevMessages, - { human: chatInput, ai: output } - ]; - setMessages(newMessagesFromAI); - - scrollToBottom(); - } catch (error) { - toast("Failed to ask question. Please try again later."); - } finally { - setIsSubmitting(false); - } - }; - - return ( -
- {/* Message threads */} -
- {messages.length < 10 && ( -
-
-
Hello 👋
-
-
- )} - {messages.map((message, index) => ( -
-
-
- -
-
-
-
- {isSubmitting && index === messages.length - 1 ? ( -
- Loading... -
-
-
-
- ) : ( - - )} -
-
-
- ))} -
- {/* Separator */} - - {/* Input */} -
-
- setText(target.value)} - onKeyDown={(e) => { - if (e.key === "Enter" && !e.shiftKey) { - e.preventDefault(); - handleSubmit(text); - } - }} - placeholder="Ask me about services, success stories, or your challenges" - aria-describedby="Ask me about services, success stories, or your challenges" - /> - -
- {/* Button */} -
- {DEFAULT_MESSAGES.map(({ text, id }) => ( - - ))} -
-
-
- ); -} - -const MarkdownContent = ({ input }: { input: string }) => { - return ( -
- ); -}; diff --git a/app/[lang]/(inferenceai)/inferenceai/components/client-wrapper.tsx b/app/[lang]/(inferenceai)/inferenceai/components/client-wrapper.tsx deleted file mode 100644 index 34e6003c..00000000 --- a/app/[lang]/(inferenceai)/inferenceai/components/client-wrapper.tsx +++ /dev/null @@ -1,24 +0,0 @@ -"use client"; - -import { usePathname } from "next/navigation"; -import type { SupportedLanguage } from "@/locales/.generated/types"; -import Nav, { Menu } from "./nav"; -import { navInferenceai, navSolutions } from "../data"; - -type ClientWrapperProps = { - lang: SupportedLanguage; -}; - -export default function ClientWrapper({ lang }: ClientWrapperProps) { - const pathname = usePathname(); - const isInferenceAiCaseStudy = pathname.includes(`/${lang}/inferenceai/`); - - const parts = pathname.split("/"); - const slug = isInferenceAiCaseStudy ? parts[parts.length - 1] : ""; - - const menus: Menu[] = isInferenceAiCaseStudy - ? navSolutions(lang, slug) - : navInferenceai(lang); - - return