Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding new design+new download functionality #13

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 126 additions & 26 deletions src/components/Playground/Playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,72 @@
"use client";

import Image from "next/image";
import React, { useState, useEffect } from "react";
import React, { useState,useRef, useEffect } from "react";
import Cli from "@/components/CLI/CLI";
import SearchBox from "@/components/Search/SearchBox";
import { Dice1, Dice3, Dice5 } from "lucide-react";
import { Dice1, Dice3, Dice5, Clock, Command, Sun, Moon, Github, Download } from "lucide-react";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove the download functionality for now, please open an issue for this we can pick up later.


import { formatTime } from "@/shared/utils/commonUtils";
import Link from "next/link";




const NavBar: React.FC<{ isDarkMode: boolean; toggleDarkMode: () => void }> = ({ isDarkMode, toggleDarkMode }) => (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want to keep things in parity with our website dicedb.io, please open an issue for DarkMode we can take this up later.

<nav className="shadow-md">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-center justify-between h-16">
<div className="flex items-center">
<Image
src="https://dicedb.io/dicedb-logo-light.png"
width={80}
height={80}
alt="DiceDB logo"
className="object-contain"
/>
<div className="ml-10 flex items-baseline space-x-4">
<Link href="#" className=" px-3 py-2 rounded-md text-sm font-medium">Docs</Link>
<Link href="#" className=" px-3 py-2 rounded-md text-sm font-medium">Blogs</Link>
<Link href="#" className=" px-3 py-2 rounded-md text-sm font-medium">
GitHub
</Link>
</div>
</div>
<div className="ml-4 flex items-center md:ml-6">
<button
onClick={toggleDarkMode}
className=" p-1 rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-800 focus:ring-white"
>
{isDarkMode ? <Sun className="h-6 w-6" /> : <Moon className="h-6 w-6" />}
</button>
</div>
</div>
</div>
</nav>
);
export default function Playground() {
const [search, setSearch] = useState("");
const [timeLeft, setTimeLeft] = useState<number>(15 * 60);
const [commandsLeft, setCommandsLeft] = useState<number>(1000);
const [isDarkMode, setIsDarkMode] = useState<boolean>(false);
const downloadBtnRef = useRef<HTMLButtonElement>(null);
const cliCodeRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const downloadBtn = downloadBtnRef.current;
const cliCode = cliCodeRef.current;

if (downloadBtn && cliCode) {
downloadBtn.addEventListener('click', () => {
const code = cliCode.textContent || '';
const blob = new Blob([code], { type: 'text/plain' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'code.txt';
link.click();
});
}
}, []);
useEffect(() => {
const timer = setInterval(() => {
setTimeLeft((prev) => (prev > 0 ? prev - 1 : 0));
Expand All @@ -25,9 +80,14 @@ export default function Playground() {
const decreaseCommandsLeft = () => {
setCommandsLeft((prev) => (prev > 0 ? prev - 1 : 0));
};
const toggleDarkMode = (): void => {
setIsDarkMode(!isDarkMode);
};

return (
<div className="container mx-auto flex flex-col flex-grow min-h-screen bg-white text-gray-900 line-height-[1.5rem]">
<NavBar isDarkMode={isDarkMode} toggleDarkMode={toggleDarkMode} />
<div className="container mx-auto px-4 py-8">
<header className="navbar flex items-center justify-between pt-5 pb-4">
<div className="flex items-center">
<Image
Expand All @@ -38,37 +98,77 @@ export default function Playground() {
className="object-contain"
/>
<h2 className="font-light text-2xl ml-2">PlayGround</h2>
<button ref={downloadBtnRef} id="download-btn" className="font-bold py-2 px-4 rounded">
<Download/>
</button>
</div>
</header>
<main className="flex flex-grow gap-10 overflow-hidden">
<div className="w-1/2 flex flex-col bg">
<div className="bg-gray-900 rounded-lg">
<div className="bg-gray-900 px-4 py-4 flex items-center rounded-lg">
<div className="flex space-x-2">
<Dice5 className="w-4 h-4 bg-red-500"></Dice5>
<Dice1 className="w-4 h-4 bg-yellow-500"></Dice1>
<Dice3 className="w-4 h-4 bg-green-500"></Dice3>
<main className="grid grid-cols-1 md:grid-cols-2 gap-8">

<div className="space-y-4">
<div className="border border-gray-300 dark:border-gray-700 rounded-lg overflow-hidden">

<div className="bg-gray-100 dark:bg-gray-800 px-4 py-2 flex items-center">

<div className="flex space-x-2">
<Dice5 className="w-4 h-4 text-red-500" />
<Dice1 className="w-4 h-4 text-yellow-500" />
<Dice3 className="w-4 h-4 text-green-500" />
</div>
</div>

<div ref={cliCodeRef} className="h-80 bg-gray-900">
<Cli decreaseCommandsLeft={decreaseCommandsLeft} />
</div>
</div>

<div className="flex justify-between">
<div className="w-[48%] border border-gray-300 dark:border-gray-700 rounded-lg p-4">
<div className="flex items-center space-x-2 mb-2">
<Clock className="text-red-600 dark:text-red-700" />
<span className="font-semibold">Cleanup in:</span>
</div>
<div className="text-2xl font-bold">{formatTime(timeLeft)}</div>
<div className="mt-2 bg-gray-200 dark:bg-gray-700 rounded-full h-2">
<div
className="bg-red-600 dark:bg-red-700 h-2 rounded-full"
style={{ width: `${(timeLeft / (15 * 60)) * 100}%` }}
></div>
</div>
</div>
<div className="w-[48%] border border-gray-300 dark:border-gray-700 rounded-lg p-4">
<div className="flex items-center space-x-2 mb-2">
<Command className="text-green-600 dark:text-green-600" />
<span className="font-semibold">Commands left:</span>
</div>
<div className="text-2xl font-bold">{commandsLeft}</div>
<div className="mt-2 bg-gray-200 dark:bg-gray-700 rounded-full h-2">
<div
className="bg-green-600 dark:bg-green-600 h-2 rounded-full"
style={{ width: `${(commandsLeft / 1000) * 100}%` }}
></div>
</div>
</div>
</div>
</div>
<div className="h-96 bg-gray-100 rounded-lg overflow-hidden shadow-md">
<Cli decreaseCommandsLeft={decreaseCommandsLeft}/>
</div>
</div>
<div className="flex flex-row justify-between text-gray-900 ">
<div className="mt-4 flex justify-between border border-gray-400 text-sm bg-transparent p-3 rounded-lg">
<span>Cleanup in : {formatTime(timeLeft)} mins</span>

<div className="space-y-4">
<div className="border rounded-lg p-4">
<SearchBox search={search} setSearch={setSearch} />
</div>
<div className="mt-4 flex justify-between border border-gray-400 text-sm bg-transparent p-3 rounded-lg">
<span>Command left: {commandsLeft}</span>
<div className="border rounded-lg p-4">
<h2 className="text-xl font-semibold mb-4">Recent Commands</h2>
<ul className="space-y-2 border">
{['SELECT * FROM users', 'INSERT INTO products', 'UPDATE orders SET status = "shipped"'].map((cmd, index) => (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why's this required?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use the browser session to populate recently run commands. I've just kept a placeholder array for now. Do you think this feature is worth implementing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now I'm not sure, let's create an issue out of it and we can pick this up later after we go live.

<li key={index} className=" border p-2 rounded">
{cmd}
</li>
))}
</ul>
</div>
</div>
</div>
<div className="w-1/2 flex flex-col">
<div className="flex-grow border border-gray-400 bg-gray-100 p-4 rounded-lg shadow-md mb-4">
<SearchBox search={search} setSearch={setSearch} />
</div>
</div>
</main>
</main>
</div>
</div>
);
}