feat(front): option popup

This commit is contained in:
Hexagonn
2024-11-02 09:04:38 +00:00
committed by GitHub
parent 26ba7d280b
commit 84c7be5689
14 changed files with 738 additions and 321 deletions

View File

@@ -4,6 +4,7 @@ import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
@@ -17,12 +18,32 @@ import useSWR from "swr";
import { getUserCount, isUserMonitored } from "@/utils/actions";
import { isSnowflake } from "@/utils/snowflake";
import Link from "next/link";
import { parameterInfo } from "@/utils/parameter";
import * as Icon from "lucide-react";
import { Checkbox } from "@/components/ui/checkbox";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { Input } from "@/components/ui/input";
import { filterLetters } from "@/lib/utils";
import { Button } from "@/components/ui/button";
export default function Home() {
const [userId, setUserId] = useState<null | string>(null);
const [userError, setUserError] = useState<string | JSX.Element>();
const [userData, setUserData] = useState<{ userId: string } | null>(null);
const originUrl = useMemo(() => window.location.origin, []);
const originUrl = useMemo(() => window.location?.origin, []);
const [copyState, setCopyState] = useState("Copy");
const [outputType, setOutputType] = useState<"markdown" | "html" | "url">(
"markdown",
@@ -30,6 +51,10 @@ export default function Home() {
const [isLoading, setIsLoading] = useState(true);
const [onImageLoaded, setOnImageLoaded] = useState(false);
const [option, setOption] = useState<
Array<{ name: string; value: string }>
>([]);
const userCount = useSWR("getUserCount", getUserCount);
const countRef = useRef<HTMLDivElement | null>(null);
useSmoothCount({
@@ -39,23 +64,26 @@ export default function Home() {
curve: [0, 1, 0, 1],
});
const outputText = () => {
const url = `${originUrl || "https://lanyard.cnrad.dev"}/api/${userData?.userId}${option.length > 0 ? `?${option.map((o) => `${o.name}=${o.value}`).join("&")}` : ""}`;
function outputText() {
if (outputType === "html") {
return `<a href="https://discord.com/users/${userData?.userId}"><img src="${originUrl || "https://lanyard.cnrad.dev"}/api/${userData?.userId}" /></a>`;
return `<a href="https://discord.com/users/${userData?.userId}"><img src="${url}" /></a>`;
} else if (outputType === "url") {
return `${originUrl || "https://lanyard.cnrad.dev"}/api/${userData?.userId}`;
return `${url}`;
} else {
return `[![Discord Presence](${originUrl || "https://lanyard.cnrad.dev"}/api/${userData?.userId})](https://discord.com/users/${userData?.userId})`;
return `[![Discord Presence](${url})](https://discord.com/users/${userData?.userId})`;
}
};
const copy = () => {
}
function copy() {
navigator.clipboard.writeText(outputText());
setCopyState("Copied!");
setTimeout(() => setCopyState("Copy"), 1500);
};
}
const submitDiscordId = async () => {
async function submitDiscordId() {
setIsLoading(true);
setOnImageLoaded(false);
setUserData(null);
@@ -82,7 +110,115 @@ export default function Home() {
setUserData({ userId });
setIsLoading(false);
};
}
function modifyOption(
data:
| {
type: "string";
name: string;
data: string;
event: React.ChangeEvent<HTMLInputElement>;
}
| {
type: "list";
name: string;
data: string;
}
| {
type: "boolean";
name: string;
data: string | boolean;
},
) {
if (data.type === "string") {
const filteredValue = filterLetters(
data.data,
(
parameterInfo.find(
(p) => p.type === "string" && p.parameter === data.name,
) as any
).options.omit,
);
setOption((prev) => {
if (data.data === "") {
return prev?.filter((o) => o.name !== data.name) || [];
} else {
if (prev?.find((o) => o.name === data.name)) {
return prev.map((o) => {
if (o.name === data.name) {
o.value = filteredValue;
}
return o;
});
} else {
return prev
? [
...prev,
{
name: data.name,
value: filteredValue,
},
]
: [
{
name: data.name,
value: filteredValue,
},
];
}
}
});
} else if (data.type === "list") {
setOption((prev) => {
if (prev?.find((o) => o.name === data.name)) {
return prev.map((o) => {
if (o.name === data.name) {
o.value = data.data;
}
return o;
});
} else {
return prev
? [...prev, { name: data.name, value: data.data }]
: [{ name: data.name, value: data.data }];
}
});
} else if (data.type === "boolean") {
setOption((prev) => {
if (prev?.find((o) => o.name === data.name)) {
return prev
.map((opt) => {
const options = parameterInfo.find(
(p) =>
p.type === "boolean" &&
p.parameter === data.name,
)?.options as { defaultBool?: boolean };
if (
data.data === (options?.defaultBool! || false)
) {
return null;
} else {
if (opt.name === data.name) {
opt.value = data.data.toString();
}
return opt;
}
})
.filter((opt) => opt !== null);
} else {
return prev
? [
...prev,
{ name: data.name, value: data.data.toString() },
]
: [{ name: data.name, value: data.data.toString() }];
}
});
}
}
return (
<>
@@ -169,16 +305,165 @@ export default function Home() {
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>
Are you absolutely sure?
</DialogTitle>
<DialogTitle>Option</DialogTitle>
<DialogDescription>
This action cannot be undone. This
will permanently delete your account
and remove your data from our
servers.
Select an option to enable/disable
features to your Lanyard Profile
</DialogDescription>
</DialogHeader>
<div className="flex max-h-[75dvh] flex-col gap-4 overflow-x-hidden overflow-y-scroll rounded-xl bg-black/50 p-4 px-6 text-[#cecece]">
{parameterInfo.map((item, idx) => {
return (
<div
key={item.parameter}
className="flex flex-col gap-1"
>
<div className="flex items-center gap-1">
<p>{item.title}</p>
<TooltipProvider
delayDuration={100}
>
<Tooltip>
<TooltipTrigger
onFocus={(
e,
) => {
e.preventDefault();
}}
>
<Icon.HelpCircleIcon
size={
18
}
/>
</TooltipTrigger>
<TooltipContent>
<p>
{
item.description
}
</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
{item.type === "string" && (
<Input
placeholder={
item.options
?.placeholder ||
"..."
}
onChange={(e) =>
modifyOption({
type: "string",
name: item.parameter,
data: e
.target
.value,
event: e,
})
}
value={
option?.find(
(o) =>
o.name ===
item.parameter,
)?.value || ""
}
/>
)}
{item.type ===
"boolean" && (
<Checkbox
onCheckedChange={(
bool,
) =>
modifyOption({
type: "boolean",
name: item.parameter,
data: bool,
})
}
checked={
option?.find(
(o) =>
o.name ===
item.parameter,
)?.value ===
"true"
? true
: option?.find(
(
o,
) =>
o.name ===
item.parameter,
)
?.value ===
"false"
? false
: item
.options
?.defaultBool ||
false
}
/>
)}
{item.type === "list" && (
<Select
onValueChange={(
val,
) =>
modifyOption({
type: "list",
name: item.parameter,
data: val,
})
}
value={
option?.find(
(o) =>
o.name ===
item.parameter,
)?.value || ""
}
>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Theme" />
</SelectTrigger>
<SelectContent>
{item.options.list.map(
(
option,
) => (
<SelectItem
value={
option.value
}
key={
option.value
}
>
{
option.name
}
</SelectItem>
),
)}
</SelectContent>
</Select>
)}
</div>
);
})}
</div>
<DialogFooter>
<Button onClick={() => setOption([])}>
Reset
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
@@ -192,7 +477,7 @@ export default function Home() {
opacity: onImageLoaded ? 1 : 0,
}}
transition={{ duration: 0.5 }}
src={`/api/${userData?.userId}`}
src={url}
height={280}
width={500}
alt="Your Lanyard Banner"