File size: 4,320 Bytes
ce9a70b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import classNames from "classnames";
import { useState } from "react";
import { toast } from "react-toastify";

import SpaceIcon from "@/assets/space.svg";
import Loading from "../loading/loading";
import { Auth } from "../../../utils/types";

function LoadButton({

  auth,

  setHtml,

}: {

  auth?: Auth;

  setHtml: (html: string) => void;

}) {
  const [open, setOpen] = useState(false);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(false);
  const [path, setPath] = useState<string | undefined>(undefined);

  const loadSpace = async () => {
    setLoading(true);
    try {
      const res = await fetch(`/api/remix/${path}`);
      const data = await res.json();
      if (res.ok) {
        if (data.html) {
          setHtml(data.html);
          toast.success("Project loaded successfully.");
        }
        setOpen(false);
      } else {
        toast.error(data.message);
        setError(data.message);
      }
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
    } catch (error: any) {
      toast.error(error.message);
      setError(error.message);
    }
    setLoading(false);
  };

  return (
    <div

      className={classNames("max-md:hidden", {

        "border-r border-gray-700 pr-5": auth,

      })}

    >

      <p

        className="underline hover:text-white cursor-pointer text-xs lg:text-sm text-gray-300"

        onClick={() => setOpen(!open)}

      >

        Load project

      </p>

      <div

        className={classNames(

          "h-screen w-screen bg-black/20 fixed left-0 top-0 z-10",

          {

            "opacity-0 pointer-events-none": !open,

          }

        )}

        onClick={() => setOpen(false)}

      ></div>

      <div

        className={classNames(

          "absolute top-[calc(100%+8px)] right-2 z-10 w-80 bg-white border border-gray-200 rounded-lg shadow-lg transition-all duration-75 overflow-hidden",

          {

            "opacity-0 pointer-events-none": !open,

          }

        )}

      >

        <>

          <header className="flex items-center text-sm px-4 py-2 border-b border-gray-200 gap-2 bg-gray-100 font-semibold text-gray-700">

            <span className="text-xs bg-pink-500/10 text-pink-500 rounded-full pl-1.5 pr-2.5 py-0.5 flex items-center justify-start gap-1.5">

              <img src={SpaceIcon} alt="Space Icon" className="size-4" />

              Space

            </span>

            Load Project

          </header>

          <main className="px-4 pt-3 pb-4 space-y-3">

            <label className="block">

              <p className="text-gray-600 text-sm font-medium mb-1.5">

                Space URL

              </p>

              <input

                type="text"

                value={path}

                className="mr-2 border rounded-md px-3 py-1.5 border-gray-300 w-full text-sm"

                placeholder="https://huggingface.co/spaces/username/space-name"

                onChange={(e) => setPath(e.target.value)}

                onFocus={() => setError(false)}

                onBlur={(e) => {

                  const pathParts = e.target.value.split("/");

                  setPath(

                    `${pathParts[pathParts.length - 2]}/${

                      pathParts[pathParts.length - 1]

                    }`

                  );

                  setError(false);

                }}

              />

            </label>

            {error && (

              <p className="text-red-500 text-xs bg-red-500/10 rounded-md p-2 break-all">

                {error}

              </p>

            )}

            <div className="pt-2 text-right">

              <button

                disabled={error || loading || !path}

                className="relative rounded-full bg-black px-5 py-2 text-white font-semibold text-xs hover:bg-black/90 transition-all duration-100 disabled:bg-gray-300 disabled:text-gray-500 disabled:cursor-not-allowed disabled:hover:bg-gray-300"

                onClick={loadSpace}

              >

                Load Project

                {loading && <Loading />}

              </button>

            </div>

          </main>

        </>

      </div>
    </div>
  );
}
export default LoadButton;