Skip to content

Commit

Permalink
Merge pull request #47 from FalkorDB/staging
Browse files Browse the repository at this point in the history
Staging
  • Loading branch information
Naseem77 authored Feb 19, 2025
2 parents 0799ed9 + ccb7f9d commit b991545
Show file tree
Hide file tree
Showing 16 changed files with 1,443 additions and 529 deletions.
181 changes: 181 additions & 0 deletions ui/app/components/ContactUsSheet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription } from "@/components/ui/sheet";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Checkbox } from "@/components/ui/checkbox";
import { useState } from "react";
import { CheckCircleIcon } from "@heroicons/react/24/solid";
import Image from "next/image";
import Logo from "../../public/logo.svg";

interface ContactUsSheetProps {
isOpen: boolean;
setIsOpen: (open: boolean) => void;
}

const isValidEmail = (email: string) => {
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
return emailRegex.test(email);
};

export default function ContactUsSheet({ isOpen, setIsOpen }: ContactUsSheetProps) {
const [step, setStep] = useState(1);
const [selectedOptions, setSelectedOptions] = useState<string[]>([]);
const [formData, setFormData] = useState({ name: "", email: "", company: "", message: "" });
const [submitted, setSubmitted] = useState(false);

const resetForm = () => {
setStep(1);
setSelectedOptions([]);
setFormData({ name: "", email: "", company: "", message: "" });
setSubmitted(false);
};

const handleCheckboxChange = (option: string) => {
setSelectedOptions((prev) =>
prev.includes(option) ? prev.filter((item) => item !== option) : [...prev, option]
);
};

const handleSubmit = async () => {
if (!formData.name || !isValidEmail(formData.email) || !formData.company) return;

const portalId = process.env.NEXT_PUBLIC_HUBSPOT_PORTAL_ID;
const formId = process.env.NEXT_PUBLIC_HUBSPOT_FORM_ID;

if (!portalId || !formId) {
console.error("Error: Missing HubSpot portal or form ID.");
return;
}

const url = `https://api.hsforms.com/submissions/v3/integration/submit/${portalId}/${formId}`;
const selectedMessage = selectedOptions.join(", ");

const data = {
fields: [
{ name: "firstname", value: formData.name },
{ name: "email", value: formData.email },
{ name: "company", value: formData.company },
{ name: "message", value: selectedMessage }
],
context: {
pageUri: window.location.href,
pageName: document.title
}
};

try {
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: JSON.stringify(data)
});

const responseData = await response.json();

if (response.ok) {
setSubmitted(true);
setTimeout(() => {
setIsOpen(false);
resetForm();
}, 1500);
} else {
console.error("HubSpot Submission Error:", responseData);
}
} catch (error) {
console.error("Network Error:", error);
}
};

return (
<Sheet
open={isOpen}
onOpenChange={(open) => {
setIsOpen(open);
if (!open) resetForm();
}}
>
<SheetContent className="w-full max-w-md p-6">
{submitted ? (
<div className="flex flex-col items-center justify-center h-full">
<CheckCircleIcon className="w-20 h-20 text-green-500" />
<p className="mt-4 text-lg font-semibold">Thank you, you&apos;re all set.</p>
<p className="text-gray-500">We’ll be in touch shortly!</p>
</div>
) : (
<>
<SheetHeader className="flex flex-col items-center mt-20">
<Image src={Logo} alt="FalkorDB Logo" width={150} height={40} className="mb-4" />
<SheetTitle className="text-center text-[1.45rem] font-bold">Let&apos;s talk about your use case</SheetTitle>
<SheetDescription className="text-center text-lg">Get a follow-up from FalkorDB</SheetDescription>
</SheetHeader>
{step === 1 ? (
<div className="mt-10">
<h2 className="text-sm text-gray-500">STEP 1 OF 2</h2>
<p className="mt-2 text-[1.25rem] font-bold">What are you working on?</p>
<div className="mt-6 space-y-2">
{[
"Already doing RAG",
"Wants to start using RAG",
"Want to start using GraphRAG",
"Interested in CodeGraph (Code Analysis)"
].map((option) => (
<div key={option} className="flex items-center gap-2">
<Checkbox
checked={selectedOptions.includes(option)}
onCheckedChange={() => handleCheckboxChange(option)}
/>
<span>{option}</span>
</div>
))}
</div>
<Button className="mt-6 w-full bg-black text-white py-2" onClick={() => setStep(2)} disabled={selectedOptions.length === 0}>
Next
</Button>
<p className="mt-4 text-xs text-gray-500 text-center">
I agree that my submitted data is being collected and stored. <strong>We don&apos;t resell your data.</strong>
</p>
</div>
) : (
<div className="mt-6">
<h2 className="text-sm text-gray-500">STEP 2 OF 2</h2>
<p className="mt-2 text-lg font-bold">Let&apos;s get acquainted</p>
<div className="mt-4 space-y-4">
<Input
placeholder="Your Name"
value={formData.name}
onChange={(e) => setFormData((prev) => ({ ...prev, name: e.target.value }))}
/>
<Input
placeholder="Email"
type="email"
value={formData.email}
onChange={(e) => setFormData((prev) => ({ ...prev, email: e.target.value }))}
/>
<Input
placeholder="Company Name"
value={formData.company}
onChange={(e) => setFormData((prev) => ({ ...prev, company: e.target.value }))}
/>
</div>
<div className="mt-6 flex justify-between">
<Button variant="secondary" onClick={() => setStep(1)}>
Back
</Button>
<Button className="bg-green-500 text-white py-2" onClick={handleSubmit} disabled={!formData.name || !isValidEmail(formData.email) || !formData.company}>
Submit
</Button>
</div>
<p className="mt-4 text-xs text-gray-500 text-center">
I agree that my submitted data is being collected and stored. <strong>We don&apos;t resell your data.</strong>
</p>
</div>
)}
</>
)}
</SheetContent>
</Sheet>
);
}
26 changes: 26 additions & 0 deletions ui/app/components/HardwareInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { HoverCard, HoverCardContent, HoverCardTrigger } from "@/components/ui/hover-card";

export function HardwareInfo({ cpu, ram, storage }: { cpu: string; ram: string; storage: string }) {
return (
<HoverCard>
<HoverCardTrigger>
<span className="inline-block w-4 h-4 bg-gray-400 text-white rounded-full text-center text-xs font-bold cursor-pointer">
i
</span>
</HoverCardTrigger>
<HoverCardContent className="bg-gray-50 text-gray-900 p-4 rounded-lg shadow-md max-w-sm border border-gray-200">
<div className="space-y-2">
<p className="text-sm">
<strong className="font-semibold text-gray-700">CPU:</strong> {cpu}
</p>
<p className="text-sm">
<strong className="font-semibold text-gray-700">RAM:</strong> {ram}
</p>
<p className="text-sm">
<strong className="font-semibold text-gray-700">Storage:</strong> {storage}
</p>
</div>
</HoverCardContent>
</HoverCard>
);
}
87 changes: 41 additions & 46 deletions ui/app/components/HorizontalBarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,20 @@ interface HorizontalBarChartProps {
data: { [key: string]: any }[];
dataKey: string;
chartLabel: string;
title: string;
subTitle: string;
yAxisTitle: string;
unit?: string;
ratio: number;
maxValue: number;
minValue: number;
}

const HorizontalBarChart: React.FC<HorizontalBarChartProps> = ({
data,
dataKey,
chartLabel,
title,
subTitle,
yAxisTitle,
unit
unit,
ratio,
maxValue,
minValue
}) => {
const containerRef = useRef<null | HTMLDivElement>(null);
const chartRef = useRef<Chart | null>(null);
Expand All @@ -63,78 +63,73 @@ const HorizontalBarChart: React.FC<HorizontalBarChartProps> = ({
backgroundColor: backgroundColors,
borderRadius: 8,
barThickness: "flex" as const,
categoryPercentage: 1,
categoryPercentage: 1.1,
},
],
};

const maxDataValue = Math.max(...data.map((item) => item[dataKey]));

const options = {
indexAxis: "y" as const,
responsive: true,

maintainAspectRatio: false,
plugins: {
title: {
display: true,
text: title,
font: {
size: 20,
weight: "bold" as const,
},
padding: {
bottom: 2,
},
legend: {
display: false,
},
subtitle: {
display: true,
text: subTitle,
datalabels: {
anchor: "end" as const,
align: "right" as const,
color: "grey",
font: {
size: 12,
weight: "normal" as const,
weight: "bold" as const,
family: "font-fira",
size: 18,
},
padding: {
bottom: 2,
// eslint-disable-next-line
formatter: (_: any, context: { dataIndex: any; dataset: { data: { [x: string]: any; }; }; }) => {
const index = context.dataIndex;
const value = context.dataset.data[index];

return value === maxValue ? ` x${ratio} ` : "";
},
},
legend: {
display: false,
},
},
scales: {
x: {
beginAtZero: true,
max: maxDataValue * 1.1,
grid: {
display: false,
},
max: maxValue * 1.1,
ticks: {
padding: 10,
font: {
size: 14,
size: 15,
family: "font-fira",
},
stepSize: dataKey === "memory" ? 5000 : 300,
color: "#333",
// eslint-disable-next-line
callback: function (value: any) {
return `${Math.round(Number(value)).toLocaleString()}${unit}`;
},
callback: (value: any) => `${Math.round(value)}${unit}`,
stepSize: dataKey === "memory" ? maxValue / 5 : minValue / 0.5,
},
},
y: {
grid: {
display: false,
drawBorder: false,
},
title: {
display: true,
text: yAxisTitle,
},
y: {
ticks: {
font: {
size: 16,
family: "font-fira",
},
color: "#333",
},
grid: {
display: false,
drawBorder: false,
},
},
},
};


return (
<div ref={containerRef} className="w-full h-full relative">
Expand Down
Loading

0 comments on commit b991545

Please sign in to comment.