File size: 4,195 Bytes
1b00a6d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;