gaojintao01
Add files using Git LFS
f8b5d42
import { useState, useRef } from "react";
import { useTranslation } from "react-i18next";
import CommunityHub from "@/models/communityHub";
import showToast from "@/utils/toast";
import paths from "@/utils/paths";
import { X } from "@phosphor-icons/react";
import { Link } from "react-router-dom";
export default function SystemPrompts({ entity }) {
const { t } = useTranslation();
const formRef = useRef(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const [tags, setTags] = useState([]);
const [tagInput, setTagInput] = useState("");
const [visibility, setVisibility] = useState("public");
const [isSuccess, setIsSuccess] = useState(false);
const [itemId, setItemId] = useState(null);
const handleSubmit = async (e) => {
e.preventDefault();
e.stopPropagation();
setIsSubmitting(true);
try {
const form = new FormData(formRef.current);
const data = {
name: form.get("name"),
description: form.get("description"),
prompt: form.get("prompt"),
tags: tags,
visibility: visibility,
};
const { success, error, itemId } =
await CommunityHub.createSystemPrompt(data);
if (!success) throw new Error(error);
setItemId(itemId);
setIsSuccess(true);
} catch (error) {
console.error("Failed to publish prompt:", error);
showToast(`Failed to publish prompt: ${error.message}`, "error", {
clear: true,
});
} finally {
setIsSubmitting(false);
}
};
const handleKeyDown = (e) => {
if (e.key === "Enter" || e.key === ",") {
e.preventDefault();
const value = tagInput.trim();
if (value.length > 20) return;
if (value && !tags.includes(value)) {
setTags((prevTags) => [...prevTags, value].slice(0, 5)); // Limit to 5 tags
setTagInput("");
}
}
};
const removeTag = (tagToRemove) => {
setTags(tags.filter((tag) => tag !== tagToRemove));
};
if (isSuccess) {
return (
<div className="p-6 -mt-12 w-[400px]">
<div className="flex flex-col items-center justify-center gap-y-2">
<h3 className="text-lg font-semibold text-theme-text-primary">
{t("community_hub.publish.system_prompt.success_title")}
</h3>
<p className="text-lg text-theme-text-primary text-center max-w-2xl">
{t("community_hub.publish.system_prompt.success_description")}
</p>
<p className="text-theme-text-secondary text-center text-sm">
{t("community_hub.publish.system_prompt.success_thank_you")}
</p>
<Link
to={paths.communityHub.viewItem("system-prompt", itemId)}
target="_blank"
rel="noreferrer"
className="w-[265px] bg-theme-bg-secondary hover:bg-theme-sidebar-item-hover text-theme-text-primary py-2 px-4 rounded-lg transition-colors mt-4 text-sm font-semibold text-center"
>
{t("community_hub.publish.system_prompt.view_on_hub")}
</Link>
</div>
</div>
);
}
return (
<>
<div className="w-full flex gap-x-2 items-center mb-3 -mt-8">
<h3 className="text-xl font-semibold text-theme-text-primary px-6 py-3">
{t(`community_hub.publish.system_prompt.modal_title`)}
</h3>
</div>
<form ref={formRef} className="flex" onSubmit={handleSubmit}>
<div className="w-1/2 p-6 pt-0 space-y-4">
<div>
<label className="block text-sm font-semibold text-theme-text-primary mb-1">
{t("community_hub.publish.system_prompt.name_label")}
</label>
<div className="text-xs text-theme-text-secondary mb-2">
{t("community_hub.publish.system_prompt.name_description")}
</div>
<input
type="text"
name="name"
required
minLength={3}
maxLength={300}
placeholder={t(
"community_hub.publish.system_prompt.name_placeholder"
)}
className="border-none w-full bg-theme-bg-secondary rounded-lg p-2 text-theme-text-primary text-sm focus:outline-primary-button active:outline-primary-button outline-none placeholder:text-theme-text-placeholder"
/>
</div>
<div>
<label className="block text-sm font-semibold text-theme-text-primary mb-1">
{t("community_hub.publish.system_prompt.description_label")}
</label>
<div className="text-xs text-white/60 mb-2">
{t("community_hub.publish.system_prompt.description_description")}
</div>
<textarea
name="description"
required
minLength={10}
maxLength={1000}
placeholder={t(
"community_hub.publish.system_prompt.description_description"
)}
className="border-none w-full bg-theme-bg-secondary rounded-lg p-2 text-white text-sm focus:outline-primary-button active:outline-primary-button outline-none min-h-[80px] placeholder:text-theme-text-placeholder"
/>
</div>
<div>
<label className="block text-sm font-semibold text-white mb-1">
{t("community_hub.publish.system_prompt.tags_label")}
</label>
<div className="text-xs text-white/60 mb-2">
{t("community_hub.publish.system_prompt.tags_description")}
</div>
<div className="flex flex-wrap gap-2 p-2 bg-theme-bg-secondary rounded-lg min-h-[42px]">
{tags.map((tag, index) => (
<span
key={index}
className="flex items-center gap-1 px-2 py-1 text-sm text-theme-text-primary bg-white/10 light:bg-black/10 rounded-md"
>
{tag}
<button
type="button"
onClick={() => removeTag(tag)}
className="border-none text-theme-text-primary hover:text-theme-text-secondary cursor-pointer"
>
<X size={14} />
</button>
</span>
))}
<input
type="text"
value={tagInput}
onChange={(e) => setTagInput(e.target.value)}
onKeyDown={handleKeyDown}
placeholder={t(
"community_hub.publish.system_prompt.tags_placeholder"
)}
className="flex-1 min-w-[200px] border-none text-sm bg-transparent text-theme-text-primary placeholder:text-theme-text-placeholder p-0 h-[24px] focus:outline-none"
/>
</div>
</div>
<div>
<label className="block text-sm font-semibold text-white mb-1">
{t("community_hub.publish.system_prompt.visibility_label")}
</label>
<div className="text-xs text-white/60 mb-2">
{visibility === "public"
? t("community_hub.publish.system_prompt.public_description")
: t("community_hub.publish.system_prompt.private_description")}
</div>
<div className="w-fit h-[42px] bg-theme-bg-secondary rounded-lg p-0.5">
<div className="flex items-center" role="group">
<input
type="radio"
id="public"
name="visibility"
value="public"
className="peer/public hidden"
defaultChecked
onChange={(e) => setVisibility(e.target.value)}
/>
<input
type="radio"
id="private"
name="visibility"
value="private"
className="peer/private hidden"
onChange={(e) => setVisibility(e.target.value)}
/>
<label
htmlFor="public"
className="h-[36px] px-4 rounded-lg text-sm font-medium transition-all duration-200 cursor-pointer text-theme-text-primary hover:text-theme-text-secondary peer-checked/public:bg-theme-sidebar-item-hover peer-checked/public:text-theme-primary-button flex items-center justify-center"
>
Public
</label>
<label
htmlFor="private"
className="h-[36px] px-4 rounded-lg text-sm font-medium transition-all duration-200 cursor-pointer text-theme-text-primary hover:text-theme-text-secondary peer-checked/private:bg-theme-sidebar-item-hover peer-checked/private:text-theme-primary-button flex items-center justify-center"
>
Private
</label>
</div>
</div>
</div>
</div>
<div className="w-1/2 p-6 pt-0 space-y-4">
<div>
<label className="block text-sm font-semibold text-white mb-1">
{t("community_hub.publish.system_prompt.prompt_label")}
</label>
<div className="text-xs text-white/60 mb-2">
{t("community_hub.publish.system_prompt.prompt_description")}
</div>
<textarea
name="prompt"
required
minLength={10}
defaultValue={entity}
placeholder={t(
"community_hub.publish.system_prompt.prompt_placeholder"
)}
className="border-none w-full bg-theme-bg-secondary rounded-lg p-2 text-white text-sm focus:outline-primary-button active:outline-primary-button outline-none min-h-[300px] placeholder:text-theme-text-placeholder"
/>
</div>
<button
type="submit"
disabled={isSubmitting}
className="border-none w-full bg-cta-button hover:opacity-80 text-theme-text-primary font-medium py-2 px-4 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
{isSubmitting
? t("community_hub.publish.system_prompt.submitting")
: t("community_hub.publish.system_prompt.publish_button")}
</button>
</div>
</form>
</>
);
}