enzostvs HF Staff commited on
Commit
30fd5be
·
1 Parent(s): c5538be

history states

Browse files
src/components/App.tsx CHANGED
@@ -37,6 +37,9 @@ function App() {
37
  "editor"
38
  );
39
  const [prompts, setPrompts] = useState<string[]>([]);
 
 
 
40
 
41
  const fetchMe = async () => {
42
  const res = await fetch("/api/@me");
@@ -201,7 +204,7 @@ function App() {
201
  }
202
  )}
203
  >
204
- <Tabs />
205
  <div
206
  onClick={(e) => {
207
  if (isAiWorking) {
@@ -236,7 +239,18 @@ function App() {
236
  </div>
237
  <AskAI
238
  html={html}
239
- setHtml={setHtml}
 
 
 
 
 
 
 
 
 
 
 
240
  isAiWorking={isAiWorking}
241
  setisAiWorking={setisAiWorking}
242
  setView={setCurrentView}
 
37
  "editor"
38
  );
39
  const [prompts, setPrompts] = useState<string[]>([]);
40
+ const [htmlHistory, setHtmlHistory] = useState<
41
+ { html: string; createdAt: Date; prompt: string }[]
42
+ >([]);
43
 
44
  const fetchMe = async () => {
45
  const res = await fetch("/api/@me");
 
204
  }
205
  )}
206
  >
207
+ <Tabs htmlHistory={htmlHistory} setHtml={setHtml} />
208
  <div
209
  onClick={(e) => {
210
  if (isAiWorking) {
 
239
  </div>
240
  <AskAI
241
  html={html}
242
+ setHtml={(newHtml: string) => {
243
+ setHtml(newHtml);
244
+ }}
245
+ onSuccess={(finalHtml: string, p: string) => {
246
+ const currentHistory = [...htmlHistory];
247
+ currentHistory.unshift({
248
+ html: finalHtml,
249
+ createdAt: new Date(),
250
+ prompt: p,
251
+ });
252
+ setHtmlHistory(currentHistory);
253
+ }}
254
  isAiWorking={isAiWorking}
255
  setisAiWorking={setisAiWorking}
256
  setView={setCurrentView}
src/components/ask-ai/ask-ai.tsx CHANGED
@@ -23,6 +23,7 @@ function AskAI({
23
  setisAiWorking,
24
  setView,
25
  onNewPrompt,
 
26
  }: {
27
  html: string;
28
  setHtml: (html: string) => void;
@@ -31,6 +32,7 @@ function AskAI({
31
  onNewPrompt: (prompt: string) => void;
32
  setView: React.Dispatch<React.SetStateAction<"editor" | "preview">>;
33
  setisAiWorking: React.Dispatch<React.SetStateAction<boolean>>;
 
34
  }) {
35
  const [open, setOpen] = useState(false);
36
  const [prompt, setPrompt] = useState("");
@@ -90,8 +92,8 @@ function AskAI({
90
  const { done, value } = await reader.read();
91
  if (done) {
92
  toast.success("AI responded successfully");
93
- setPrompt("");
94
  setPreviousPrompt(prompt);
 
95
  setisAiWorking(false);
96
  setHasAsked(true);
97
  audio.play();
@@ -104,6 +106,7 @@ function AskAI({
104
  if (finalDoc) {
105
  setHtml(finalDoc);
106
  }
 
107
 
108
  return;
109
  }
@@ -153,11 +156,10 @@ function AskAI({
153
  >
154
  {defaultHTML !== html && (
155
  <p
156
- className="text-2xl text-white/50 hover:text-white/80 -translate-y-[calc(100%+8px)] absolute top-0 right-0 cursor-pointer"
157
  onClick={() => {
158
  copyToClipboard(html);
159
  toast.success("HTML copied to clipboard");
160
- audio.play();
161
  }}
162
  >
163
  <IoCopy />
 
23
  setisAiWorking,
24
  setView,
25
  onNewPrompt,
26
+ onSuccess,
27
  }: {
28
  html: string;
29
  setHtml: (html: string) => void;
 
32
  onNewPrompt: (prompt: string) => void;
33
  setView: React.Dispatch<React.SetStateAction<"editor" | "preview">>;
34
  setisAiWorking: React.Dispatch<React.SetStateAction<boolean>>;
35
+ onSuccess: (h: string, p: string) => void;
36
  }) {
37
  const [open, setOpen] = useState(false);
38
  const [prompt, setPrompt] = useState("");
 
92
  const { done, value } = await reader.read();
93
  if (done) {
94
  toast.success("AI responded successfully");
 
95
  setPreviousPrompt(prompt);
96
+ setPrompt("");
97
  setisAiWorking(false);
98
  setHasAsked(true);
99
  audio.play();
 
106
  if (finalDoc) {
107
  setHtml(finalDoc);
108
  }
109
+ onSuccess(finalDoc ?? contentResponse, prompt);
110
 
111
  return;
112
  }
 
156
  >
157
  {defaultHTML !== html && (
158
  <p
159
+ className="text-xl text-white/50 hover:text-white/80 -translate-y-[calc(100%+8px)] absolute top-0 right-0 cursor-pointer"
160
  onClick={() => {
161
  copyToClipboard(html);
162
  toast.success("HTML copied to clipboard");
 
163
  }}
164
  >
165
  <IoCopy />
src/components/tabs/tabs.tsx CHANGED
@@ -1,16 +1,107 @@
 
 
 
 
1
  import Deepseek from "./../../assets/deepseek-color.svg";
2
 
3
- function Tabs({ children }: { children?: React.ReactNode }) {
 
 
 
 
 
 
 
 
 
 
4
  return (
5
  <div className="border-b border-gray-800 pl-4 lg:pl-7 pr-3 flex items-center justify-between">
6
- <div
7
- className="
8
- space-x-6"
9
- >
10
- <button className="rounded-md text-sm cursor-pointer transition-all duration-100 font-medium relative py-2.5 text-white">
11
- index.html
12
- <span className="absolute bottom-0 left-0 h-0.5 w-full transition-all duration-100 bg-white" />
13
- </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  </div>
15
  <div className="flex items-center justify-end gap-3">
16
  <a
 
1
+ import { useState } from "react";
2
+ import classNames from "classnames";
3
+ import { IoTimeOutline } from "react-icons/io5";
4
+
5
  import Deepseek from "./../../assets/deepseek-color.svg";
6
 
7
+ function Tabs({
8
+ htmlHistory,
9
+ setHtml,
10
+ children,
11
+ }: {
12
+ htmlHistory?: { html: string; createdAt: Date; prompt: string }[];
13
+ setHtml: (html: string) => void;
14
+ children?: React.ReactNode;
15
+ }) {
16
+ const [visible, setVisible] = useState(false);
17
+
18
  return (
19
  <div className="border-b border-gray-800 pl-4 lg:pl-7 pr-3 flex items-center justify-between">
20
+ <div className="flex items-center justify-start gap-4 flex-1">
21
+ <div
22
+ className="
23
+ space-x-6"
24
+ >
25
+ <button className="rounded-md text-sm cursor-pointer transition-all duration-100 font-medium relative py-2.5 text-white">
26
+ index.html
27
+ <span className="absolute bottom-0 left-0 h-0.5 w-full transition-all duration-100 bg-white" />
28
+ </button>
29
+ </div>
30
+ {htmlHistory && htmlHistory?.length > 1 && (
31
+ <div
32
+ className="relative"
33
+ onMouseEnter={() => setVisible(true)}
34
+ onMouseLeave={() => setVisible(false)}
35
+ >
36
+ <button
37
+ className={classNames(
38
+ "text-gray-400 hover:text-gray-300 cursor-pointer text-sm nderline flex items-center justify-start gap-1",
39
+ {
40
+ "!text-gray-300": visible,
41
+ }
42
+ )}
43
+ >
44
+ <IoTimeOutline />
45
+ {htmlHistory?.length} versions
46
+ </button>
47
+ <div
48
+ className={classNames(
49
+ "absolute bottom-0 left-0 min-w-sm w-full z-10 translate-y-full pt-2 transition-all duration-200",
50
+ {
51
+ "opacity-0 pointer-events-none": !visible,
52
+ }
53
+ )}
54
+ >
55
+ <div className="bg-gray-950 border border-gray-800 rounded-xl shadow-2xs p-4">
56
+ <p className="text-xs font-bold text-white">Version History</p>
57
+ <p className="text-gray-400 text-xs mt-1">
58
+ This is a list of the full history of what AI has done to
59
+ this.
60
+ </p>
61
+ <ul className="mt-2 max-h-[250px] overflow-y-auto">
62
+ {htmlHistory?.map((item, index) => (
63
+ <li
64
+ key={index}
65
+ className="text-gray-300 text-xs py-2 border-b border-gray-800 last:border-0 flex items-center justify-between gap-2"
66
+ >
67
+ <div className="">
68
+ <span className="line-clamp-1">{item.prompt}</span>
69
+ <span className="text-gray-500 text-[10px]">
70
+ {new Date(item.createdAt).toLocaleDateString(
71
+ "en-US",
72
+ {
73
+ month: "2-digit",
74
+ day: "2-digit",
75
+ year: "2-digit",
76
+ }
77
+ ) +
78
+ " " +
79
+ new Date(item.createdAt).toLocaleTimeString(
80
+ "en-US",
81
+ {
82
+ hour: "2-digit",
83
+ minute: "2-digit",
84
+ second: "2-digit",
85
+ hour12: false,
86
+ }
87
+ )}
88
+ </span>
89
+ </div>
90
+ <button
91
+ className="bg-pink-500 text-white text-xs font-medium rounded-md px-2 py-1 transition-all duration-100 hover:bg-pink-600 cursor-pointer"
92
+ onClick={() => {
93
+ setHtml(item.html);
94
+ }}
95
+ >
96
+ Select
97
+ </button>
98
+ </li>
99
+ ))}
100
+ </ul>
101
+ </div>
102
+ </div>
103
+ </div>
104
+ )}
105
  </div>
106
  <div className="flex items-center justify-end gap-3">
107
  <a