Spaces:
Running
Running
add login button
Browse files- components/editor/footer/index.tsx +33 -11
- components/editor/index.tsx +7 -2
- hooks/useEditor.ts +2 -2
components/editor/footer/index.tsx
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
import classNames from "classnames";
|
2 |
import { FaMobileAlt } from "react-icons/fa";
|
3 |
-
import { HelpCircle, RefreshCcw, SparkleIcon } from "lucide-react";
|
4 |
import { FaLaptopCode } from "react-icons/fa6";
|
5 |
import { HtmlHistory, Page } from "@/types";
|
6 |
import { Button } from "@/components/ui/button";
|
@@ -9,6 +9,8 @@ import { History } from "@/components/editor/history";
|
|
9 |
import { UserMenu } from "@/components/user-menu";
|
10 |
import { useUser } from "@/hooks/useUser";
|
11 |
import Link from "next/link";
|
|
|
|
|
12 |
|
13 |
const DEVICES = [
|
14 |
{
|
@@ -22,19 +24,23 @@ const DEVICES = [
|
|
22 |
];
|
23 |
|
24 |
export function Footer({
|
|
|
|
|
25 |
htmlHistory,
|
26 |
setPages,
|
27 |
device,
|
28 |
setDevice,
|
29 |
iframeRef,
|
30 |
}: {
|
|
|
|
|
31 |
htmlHistory?: HtmlHistory[];
|
32 |
device: "desktop" | "mobile";
|
33 |
setPages: (pages: Page[]) => void;
|
34 |
iframeRef?: React.RefObject<HTMLIFrameElement | null>;
|
35 |
setDevice: React.Dispatch<React.SetStateAction<"desktop" | "mobile">>;
|
36 |
}) {
|
37 |
-
const { user } = useUser();
|
38 |
|
39 |
const handleRefreshIframe = () => {
|
40 |
if (iframeRef?.current) {
|
@@ -47,11 +53,19 @@ export function Footer({
|
|
47 |
}
|
48 |
};
|
49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
return (
|
51 |
<footer className="border-t bg-slate-200 border-slate-300 dark:bg-neutral-950 dark:border-neutral-800 px-3 py-2 flex items-center justify-between sticky bottom-0 z-20">
|
52 |
<div className="flex items-center gap-2">
|
53 |
-
{user
|
54 |
-
|
55 |
<>
|
56 |
<div className="max-w-max bg-amber-500/10 rounded-full px-3 py-1 text-amber-500 border border-amber-500/20 text-sm font-semibold">
|
57 |
Local Usage
|
@@ -59,14 +73,22 @@ export function Footer({
|
|
59 |
</>
|
60 |
) : (
|
61 |
<UserMenu className="!p-1 !pr-3 !h-auto" />
|
62 |
-
)
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
New <span className="max-lg:hidden">Project</span>
|
68 |
</Button>
|
69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
{htmlHistory && htmlHistory.length > 0 && (
|
71 |
<>
|
72 |
<p className="text-neutral-700">|</p>
|
|
|
1 |
import classNames from "classnames";
|
2 |
import { FaMobileAlt } from "react-icons/fa";
|
3 |
+
import { HelpCircle, LogIn, RefreshCcw, SparkleIcon } from "lucide-react";
|
4 |
import { FaLaptopCode } from "react-icons/fa6";
|
5 |
import { HtmlHistory, Page } from "@/types";
|
6 |
import { Button } from "@/components/ui/button";
|
|
|
9 |
import { UserMenu } from "@/components/user-menu";
|
10 |
import { useUser } from "@/hooks/useUser";
|
11 |
import Link from "next/link";
|
12 |
+
import { useLocalStorage } from "react-use";
|
13 |
+
import { isTheSameHtml } from "@/lib/compare-html-diff";
|
14 |
|
15 |
const DEVICES = [
|
16 |
{
|
|
|
24 |
];
|
25 |
|
26 |
export function Footer({
|
27 |
+
pages,
|
28 |
+
isNew = false,
|
29 |
htmlHistory,
|
30 |
setPages,
|
31 |
device,
|
32 |
setDevice,
|
33 |
iframeRef,
|
34 |
}: {
|
35 |
+
pages: Page[];
|
36 |
+
isNew?: boolean;
|
37 |
htmlHistory?: HtmlHistory[];
|
38 |
device: "desktop" | "mobile";
|
39 |
setPages: (pages: Page[]) => void;
|
40 |
iframeRef?: React.RefObject<HTMLIFrameElement | null>;
|
41 |
setDevice: React.Dispatch<React.SetStateAction<"desktop" | "mobile">>;
|
42 |
}) {
|
43 |
+
const { user, openLoginWindow } = useUser();
|
44 |
|
45 |
const handleRefreshIframe = () => {
|
46 |
if (iframeRef?.current) {
|
|
|
53 |
}
|
54 |
};
|
55 |
|
56 |
+
const [, setStorage] = useLocalStorage("pages");
|
57 |
+
const handleClick = async () => {
|
58 |
+
if (pages && !isTheSameHtml(pages[0].html)) {
|
59 |
+
setStorage(pages);
|
60 |
+
}
|
61 |
+
openLoginWindow();
|
62 |
+
};
|
63 |
+
|
64 |
return (
|
65 |
<footer className="border-t bg-slate-200 border-slate-300 dark:bg-neutral-950 dark:border-neutral-800 px-3 py-2 flex items-center justify-between sticky bottom-0 z-20">
|
66 |
<div className="flex items-center gap-2">
|
67 |
+
{user ? (
|
68 |
+
user?.isLocalUse ? (
|
69 |
<>
|
70 |
<div className="max-w-max bg-amber-500/10 rounded-full px-3 py-1 text-amber-500 border border-amber-500/20 text-sm font-semibold">
|
71 |
Local Usage
|
|
|
73 |
</>
|
74 |
) : (
|
75 |
<UserMenu className="!p-1 !pr-3 !h-auto" />
|
76 |
+
)
|
77 |
+
) : (
|
78 |
+
<Button size="sm" variant="default" onClick={handleClick}>
|
79 |
+
<LogIn className="text-sm" />
|
80 |
+
Log In
|
|
|
81 |
</Button>
|
82 |
+
)}
|
83 |
+
{user && !isNew && <p className="text-neutral-700">|</p>}
|
84 |
+
{!isNew && (
|
85 |
+
<Link href="/projects/new">
|
86 |
+
<Button size="sm" variant="secondary">
|
87 |
+
<MdAdd className="text-sm" />
|
88 |
+
New <span className="max-lg:hidden">Project</span>
|
89 |
+
</Button>
|
90 |
+
</Link>
|
91 |
+
)}
|
92 |
{htmlHistory && htmlHistory.length > 0 && (
|
93 |
<>
|
94 |
<p className="text-neutral-700">|</p>
|
components/editor/index.tsx
CHANGED
@@ -39,11 +39,14 @@ export const AppEditor = ({
|
|
39 |
images?: string[];
|
40 |
isNew?: boolean;
|
41 |
}) => {
|
42 |
-
console.log(project?.prompts);
|
43 |
const [htmlStorage, , removeHtmlStorage] = useLocalStorage("pages");
|
44 |
const [, copyToClipboard] = useCopyToClipboard();
|
45 |
const { htmlHistory, setHtmlHistory, prompts, setPrompts, pages, setPages } =
|
46 |
-
useEditor(
|
|
|
|
|
|
|
|
|
47 |
|
48 |
const searchParams = useSearchParams();
|
49 |
const router = useRouter();
|
@@ -376,10 +379,12 @@ export const AppEditor = ({
|
|
376 |
/>
|
377 |
</main>
|
378 |
<Footer
|
|
|
379 |
htmlHistory={htmlHistory}
|
380 |
setPages={setPages}
|
381 |
iframeRef={iframeRef}
|
382 |
device={device}
|
|
|
383 |
setDevice={setDevice}
|
384 |
/>
|
385 |
</section>
|
|
|
39 |
images?: string[];
|
40 |
isNew?: boolean;
|
41 |
}) => {
|
|
|
42 |
const [htmlStorage, , removeHtmlStorage] = useLocalStorage("pages");
|
43 |
const [, copyToClipboard] = useCopyToClipboard();
|
44 |
const { htmlHistory, setHtmlHistory, prompts, setPrompts, pages, setPages } =
|
45 |
+
useEditor(
|
46 |
+
initialPages,
|
47 |
+
project?.prompts ?? [],
|
48 |
+
typeof htmlStorage === "string" ? htmlStorage : undefined
|
49 |
+
);
|
50 |
|
51 |
const searchParams = useSearchParams();
|
52 |
const router = useRouter();
|
|
|
379 |
/>
|
380 |
</main>
|
381 |
<Footer
|
382 |
+
pages={pages}
|
383 |
htmlHistory={htmlHistory}
|
384 |
setPages={setPages}
|
385 |
iframeRef={iframeRef}
|
386 |
device={device}
|
387 |
+
isNew={isNew}
|
388 |
setDevice={setDevice}
|
389 |
/>
|
390 |
</section>
|
hooks/useEditor.ts
CHANGED
@@ -2,7 +2,7 @@ import { defaultHTML } from "@/lib/consts";
|
|
2 |
import { HtmlHistory, Page } from "@/types";
|
3 |
import { useState } from "react";
|
4 |
|
5 |
-
export const useEditor = (initialPages?: Page[], initialPrompts?: string[]) => {
|
6 |
/**
|
7 |
* State to manage the HTML content of the editor.
|
8 |
* This will be the main content that users edit.
|
@@ -10,7 +10,7 @@ export const useEditor = (initialPages?: Page[], initialPrompts?: string[]) => {
|
|
10 |
const [pages, setPages] = useState<Array<Page>>(initialPages ??[
|
11 |
{
|
12 |
path: "index.html",
|
13 |
-
html: defaultHTML,
|
14 |
},
|
15 |
]);
|
16 |
/**
|
|
|
2 |
import { HtmlHistory, Page } from "@/types";
|
3 |
import { useState } from "react";
|
4 |
|
5 |
+
export const useEditor = (initialPages?: Page[], initialPrompts?: string[], initialHtmlStorage?: string) => {
|
6 |
/**
|
7 |
* State to manage the HTML content of the editor.
|
8 |
* This will be the main content that users edit.
|
|
|
10 |
const [pages, setPages] = useState<Array<Page>>(initialPages ??[
|
11 |
{
|
12 |
path: "index.html",
|
13 |
+
html: initialHtmlStorage ?? defaultHTML,
|
14 |
},
|
15 |
]);
|
16 |
/**
|