This commit is contained in:
Sabda Yagra 2025-09-09 00:26:30 +07:00
parent aee612f3f5
commit ce6ca9e853
8 changed files with 1811 additions and 819 deletions

View File

@ -1,19 +1,19 @@
import { Card, CardContent } from "@/components/ui/card"; // import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb"; // import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form"; // import FormTask from "@/components/form/task/task-form";
import FormTaskDetail from "@/components/form/task/task-detail-form"; // import FormTaskDetail from "@/components/form/task/task-detail-form";
import FormDetailInternal from "@/components/form/communication/internal-detail-form"; // import FormDetailInternal from "@/components/form/communication/internal-detail-form";
import FormDetailTicketing from "@/components/form/ticketing/ticketing-detail-form"; // import FormDetailTicketing from "@/components/form/ticketing/ticketing-detail-form";
const TicketingDetailPage = async () => { // const TicketingDetailPage = async () => {
return ( // return (
<div> // <div>
<SiteBreadcrumb /> // <SiteBreadcrumb />
<div className="space-y-4"> // <div className="space-y-4">
<FormDetailTicketing /> // <FormDetailTicketing />
</div> // </div>
</div> // </div>
); // );
}; // };
export default TicketingDetailPage; // export default TicketingDetailPage;

View File

@ -8,11 +8,11 @@ const TicketingPage = async () => {
<section <section
id="table" id="table"
className="flex flex-col gap-2 bg-white rounded-lg p-3 mt-5" className="flex flex-col gap-2 bg-white dark:bg-black rounded-lg p-3 mt-5"
> >
<div className="flex justify-between py-3"> {/* <div className="flex justify-between py-3">
<p className="text-lg">Semua Ticket</p> <p className="text-lg">Semua Ticket : 0</p>
</div> </div> */}
<TicketingTable /> <TicketingTable />
</section> </section>

View File

@ -76,12 +76,12 @@ function CustomEditor(props) {
.ckeditor-wrapper { .ckeditor-wrapper {
border-radius: 6px; border-radius: 6px;
overflow: hidden; overflow: hidden;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), // box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1),
0 1px 2px 0 rgba(0, 0, 0, 0.06); 0 1px 2px 0 rgba(0, 0, 0, 0.06);
} }
.ckeditor-wrapper :global(.ck.ck-editor__main) { .ckeditor-wrapper :global(.ck.ck-editor__main) {
min-height: ${props.height || 400}px; min-height: ${props.height || 300}px;
max-height: ${maxHeight}px; max-height: ${maxHeight}px;
} }

View File

@ -44,6 +44,7 @@ import {
getDetailArticle, getDetailArticle,
getGenerateKeywords, getGenerateKeywords,
getGenerateTitle, getGenerateTitle,
translateText,
} from "@/service/content/ai"; } from "@/service/content/ai";
import { getCookiesDecrypt } from "@/lib/utils"; import { getCookiesDecrypt } from "@/lib/utils";
import { useDropzone } from "react-dropzone"; import { useDropzone } from "react-dropzone";
@ -109,7 +110,8 @@ export default function FormImage() {
const [editingArticleId, setEditingArticleId] = useState<string | null>(null); const [editingArticleId, setEditingArticleId] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState<boolean>(false); const [isLoading, setIsLoading] = useState<boolean>(false);
const [isLoadingData, setIsLoadingData] = useState<boolean>(false); const [isLoadingData, setIsLoadingData] = useState<boolean>(false);
const [localContent, setLocalContent] = useState("");
const [isLoadingTranslate, setIsLoadingTranslate] = useState(false);
const [articleIds, setArticleIds] = useState<string[]>([]); const [articleIds, setArticleIds] = useState<string[]>([]);
const [isGeneratedArticle, setIsGeneratedArticle] = useState(false); const [isGeneratedArticle, setIsGeneratedArticle] = useState(false);
const [articleBody, setArticleBody] = useState<string>(""); const [articleBody, setArticleBody] = useState<string>("");
@ -408,6 +410,17 @@ export default function FormImage() {
Cookies.set("nulisAIArticleIdTemp", JSON.stringify(articleIds)); Cookies.set("nulisAIArticleIdTemp", JSON.stringify(articleIds));
}; };
async function doTranslate() {
const data = {
text: "Hello World",
sourceLang: "EN",
targetLang: "ID",
};
const result = await translateText(data);
console.log("Hasil Translate:", result);
}
const handleArticleIdClick = async (id: string) => { const handleArticleIdClick = async (id: string) => {
setIsLoadingData(true); setIsLoadingData(true);
let retryCount = 0; let retryCount = 0;
@ -1162,18 +1175,22 @@ export default function FormImage() {
</div> </div>
</div> </div>
<div className="py-3 space-y-2"> <div className="py-3 space-y-2">
{" "}
<Label> <Label>
{t("description", { defaultValue: "Description" })} {" "}
</Label> {t("description", { defaultValue: "Description" })}{" "}
</Label>{" "}
<Controller <Controller
control={control} control={control}
name="description" name="description"
render={({ field: { onChange, value } }) => render={({ field: { onChange, value } }) =>
isLoadingData ? ( isLoadingData ? (
<div className="flex justify-center items-center h-40"> <div className="flex justify-center items-center h-40">
{" "}
<p className="text-gray-500 dark:text-black"> <p className="text-gray-500 dark:text-black">
Loading Proses Data... {" "}
</p> Loading Proses Data...{" "}
</p>{" "}
</div> </div>
) : ( ) : (
<CustomEditor <CustomEditor
@ -1186,12 +1203,13 @@ export default function FormImage() {
/> />
) )
} }
/> />{" "}
{errors.description?.message && ( {errors.description?.message && (
<p className="text-red-400 text-sm"> <p className="text-red-400 text-sm">
{errors.description.message} {" "}
{errors.description.message}{" "}
</p> </p>
)} )}{" "}
</div> </div>
</div> </div>
)} )}
@ -1208,7 +1226,69 @@ export default function FormImage() {
Select Original Description Select Original Description
</Label> </Label>
</div> </div>
<div className="py-3 space-y-2"> <div className="py-3 space-y-2">
<div className="flex justify-between items-center">
<Label>
{t("description", { defaultValue: "Description" })}
</Label>
<button
type="button"
onClick={async () => {
try {
setIsLoadingTranslate(true);
const res = await translateText({
text: localContent,
sourceLang: "ID",
targetLang: "EN",
});
if (!res.error && res.data?.translatedText) {
setLocalContent(res.data.translatedText);
setValue(
"descriptionOri",
res.data.translatedText
);
setEditorContent(res.data.translatedText);
}
} catch (err) {
console.error("Translate gagal:", err);
} finally {
setIsLoadingTranslate(false);
}
}}
className="px-3 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600"
>
{isLoadingTranslate
? "Translating..."
: "Translate to English"}
</button>
</div>
{/* Editor */}
<Controller
control={control}
name="descriptionOri"
render={({ field: { onChange, value } }) => (
<CustomEditor
onChange={(val: any) => {
onChange(val);
setLocalContent(val);
setEditorContent(val);
}}
initialData={localContent || value}
/>
)}
/>
{errors.description?.message && (
<p className="text-red-400 text-sm">
{errors.description.message}
</p>
)}
</div>
{/* <div className="py-3 space-y-2">
<Label> <Label>
{t("description", { defaultValue: "Description" })} {t("description", { defaultValue: "Description" })}
</Label> </Label>
@ -1230,7 +1310,7 @@ export default function FormImage() {
{errors.description.message} {errors.description.message}
</p> </p>
)} )}
</div> </div> */}
<p className="text-sm font-semibold">Content Rewrite</p> <p className="text-sm font-semibold">Content Rewrite</p>
<div className="my-2"> <div className="my-2">

File diff suppressed because it is too large Load Diff

View File

@ -3169,7 +3169,99 @@ export function getMenuList(pathname: string, t: any): Group[] {
label: t("ticketing"), label: t("ticketing"),
active: pathname.includes("/ticketing"), active: pathname.includes("/ticketing"),
icon: "mdi:ticket-outline", icon: "mdi:ticket-outline",
submenus: [], submenus: [
{
href: "/",
label: 'All',
active: pathname.includes("/ticketing/all"),
icon: "solar:inbox-line-outline",
children: [],
},
{
href: "/",
label: 'Instagram',
active: pathname.includes("/ticketing/instagram"),
icon: "ri:chat-private-line",
children: [],
},
{
href: "/",
label: 'Facebook',
active: pathname.includes("/ticketing/facebook"),
icon: "ri:share-forward-2-fill",
children: [],
},
{
href: "/",
label: 'Youtube',
active: pathname.includes("/ticketing/youtube"),
icon: "ri:share-forward-2-fill",
children: [],
},
{
href: "/",
label: 'Tiktok',
active: pathname.includes("/ticketing/tiktok"),
icon: "ri:share-forward-2-fill",
children: [],
},
{
href: "/",
label: 'Kolom Komentar',
active: pathname.includes("/ticketing/comment"),
icon: "ri:share-forward-2-fill",
children: [],
},
{
href: "/",
label: 'Hubungi Kami',
active: pathname.includes("/ticketing/contact-us"),
icon: "ri:share-forward-2-fill",
children: [],
},
{
href: "/",
label: 'Play Store',
active: pathname.includes("/ticketing/play-store"),
icon: "ri:share-forward-2-fill",
children: [],
},
{
href: "/",
label: 'App Store',
active: pathname.includes("/ticketing/app-store"),
icon: "ri:share-forward-2-fill",
children: [],
},
{
href: "/",
label: 'Web Humas',
active: pathname.includes("/ticketing/web-humas"),
icon: "ri:share-forward-2-fill",
children: [],
},
{
href: "/",
label: 'e-PPID',
active: pathname.includes("/ticketing/e-ppid"),
icon: "ri:share-forward-2-fill",
children: [],
},
{
href: "/",
label: 'Emergency Issues',
active: pathname.includes("/ticketing/emergency-issues"),
icon: "ri:share-forward-2-fill",
children: [],
},
{
href: "/",
label: 'Campaignpool',
active: pathname.includes("/ticketing/campaignpool"),
icon: "ri:share-forward-2-fill",
children: [],
},
],
}, },
], ],
}, },

View File

@ -19,6 +19,16 @@ export async function generateDataRewrite(data: any) {
return await httpPost("ai-writer/create-rewriter", headers, data); return await httpPost("ai-writer/create-rewriter", headers, data);
} }
export async function translateText(data: any) {
const headers = {
"content-type": "application/json",
Authorization:
"Basic bmdETFBQaW9ycGx6bncyalRxVmUzWUZDejV4cUtmVUo6UHJEaERXUmNvdkJSNlc1Sg==",
};
return await httpPost("ai-writer/translation/process", headers, data);
}
export async function getGenerateTitle(data: any) { export async function getGenerateTitle(data: any) {
const headers = { const headers = {
"content-type": "application/json", "content-type": "application/json",