Skip to content

Commit

Permalink
new structure
Browse files Browse the repository at this point in the history
  • Loading branch information
rishavvajpayee committed Sep 28, 2024
1 parent e54d64f commit c85b3d3
Show file tree
Hide file tree
Showing 8 changed files with 207 additions and 13 deletions.
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"type-check": "tsc --noEmit"
},
"dependencies": {
"lucide-react": "^0.446.0",
"next": "14.2.13",
"react": "^18",
"react-dom": "^18"
Expand Down
16 changes: 4 additions & 12 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
import Image from "next/image";
import Playground from "@/components/Playground/Playground";

export default function Home() {
return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
<main className="flex flex-col gap-8 row-start-2 items-center sm:items-start">
<Image
src="/logo.png"
alt="Next.js logo"
width={180}
height={38}
priority
/>
<main>
<Playground />
</main>
</div>
);
}
}
48 changes: 47 additions & 1 deletion src/components/CLI/CLI.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,47 @@
// Feature specific

'use client';

import React from 'react';
import { useEffect, useRef } from 'react';
import { Dice1 } from 'lucide-react';

interface CliProps {
output: string[];
command: string;
setCommand: React.Dispatch<React.SetStateAction<string>>;
handleCommand: React.KeyboardEventHandler<HTMLInputElement>;
}

export default function Cli({ output, command, setCommand, handleCommand }: CliProps) {
const terminalRef = useRef<HTMLDivElement>(null);

useEffect(() => {
if (terminalRef.current) {
terminalRef.current.scrollTop = terminalRef.current.scrollHeight;
}
}, [output]);

return (
<div className="flex-grow flex flex-col">
<div ref={terminalRef} className="flex-grow overflow-auto mb-4 font-mono">
{output.map((line, index) => (
<div key={index} className={line.startsWith('dice>') ? 'text-blue-400' : 'text-green-400'}>
{line}
</div>
))}
</div>
<div className="flex items-center bg-gray-700 rounded px-2 mb-4">
<Dice1 className="w-4 h-4 text-green-500 mr-2" />
<span className="text-green-500">dice&gt;</span>
<input
type="text"
value={command}
onChange={(e) => setCommand(e.target.value)}
onKeyDown={handleCommand}
placeholder="Enter DiceDB command..."
className="bg-transparent border-none outline-none w-full py-2 text-white placeholder-gray-500 ml-2"
/>
</div>
</div>
);
}
13 changes: 13 additions & 0 deletions src/components/Footer/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

'use client';

export default function Footer({ timeLeft, triggers }: { timeLeft: string, triggers: number }) {
return (
<div className="bg-gray-100 rounded-lg p-4 text-gray-900 text-sm">
<div className="flex justify-between items-center">
<span>Cleanup in: {timeLeft} mins</span>
<span>Command Triggers left: {triggers}</span>
</div>
</div>
);
}
10 changes: 10 additions & 0 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use client';


export default function Header() {
return (
<header className="flex items-center mb-4">
<h1 className="text-2xl font-bold">DiceDB PlayGround</h1>
</header>
);
}
85 changes: 85 additions & 0 deletions src/components/Playground/Playground.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
"use client";

import React from "react";
import { useState, useEffect } from "react";
import Cli from "@/components/Cli/Cli";
import Header from "@/components/Header/Header";
import Footer from "@/components/Footer/Footer";
import SearchBox from "@/components/Search/SearchBox";

export default function Playground() {
const [command, setCommand] = useState("");
const [output, setOutput] = useState<string[]>([]);
const [triggers, setTriggers] = useState<number>(1000);
const [search, setSearch] = useState("");
const [timeLeft, setTimeLeft] = useState<number>(15 * 60);
const [store, setStore] = useState<{ [key: string]: string }>({
hello: "world",
});

const handleCommand = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter") {
const newOutput = `dice> ${command}`;
let result = "";

const [cmd, ...args] = command.split(" ");

switch (cmd.toUpperCase()) {
case "GET":
result = store[args[0]] || "(nil)";
break;
case "SET":
if (args.length === 2) {
const [key, value] = args;
setStore((prevStore) => ({ ...prevStore, [key]: value }));
result = "OK";
} else {
result = "Invalid command. Usage: SET key value";
}
break;
default:
result = `Unknown command: ${cmd}`;
}

setOutput([...output, newOutput, result]);
setCommand("");
setTriggers((prev) => prev - 1);
}
};

useEffect(() => {
const timer = setInterval(() => {
setTimeLeft((prev) => (prev > 0 ? prev - 1 : 0));
}, 1000);

return () => clearInterval(timer);
}, []);

const formatTime = (seconds: number): string => {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${minutes}:${remainingSeconds < 10 ? "0" : ""}${remainingSeconds}`;
};

return (
<>
<div className="min-h-screen flex flex-col bg-gray-900 text-gray-100 p-4">
<Header />
<main className="flex-grow flex overflow-hidden">
<div className="w-1/2 p-4 bg-gray-800 text-white flex flex-col">
<Cli
output={output}
command={command}
setCommand={setCommand}
handleCommand={(e) => handleCommand(e)}
/>
<Footer timeLeft={formatTime(timeLeft)} triggers={triggers} />
</div>
<div className="w-1/2 p-4 bg-white shadow-md overflow-auto">
<SearchBox search={search} setSearch={setSearch} />
</div>
</main>
</div>
</>
);
}
37 changes: 37 additions & 0 deletions src/components/Search/SearchBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use client';

import React from 'react';
import { Search } from 'lucide-react';
interface SearchBoxProps {
search: string;
setSearch: React.Dispatch<React.SetStateAction<string>>
}

export default function SearchBox({ search , setSearch}: SearchBoxProps) {
return (
<div>
<div className="mb-4">
<div className="flex items-center bg-gray-100 rounded px-2">
<Search className="text-gray-400 mr-2" />
<input
type="text"
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search commands..."
className="bg-transparent border-none outline-none w-full py-2 text-gray-900 placeholder-gray-500"
/>
</div>
</div>
<div className="space-y-2">
{['SET', 'GET', 'DEL'].map((cmd) => (
<button
key={cmd}
className="w-full text-left bg-gray-700 hover:bg-gray-600 rounded p-2 transition-colors"
>
{cmd}
</button>
))}
</div>
</div>
);
}

0 comments on commit c85b3d3

Please sign in to comment.