Files
ruseemrooz/dist/server/pages/admin.astro.mjs
mrfelfel dfb0e857f1 fix
2026-07-18 19:41:33 +03:30

100 lines
26 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { c as createComponent, m as maybeRenderHead, a as addAttribute, r as renderTemplate, b as createAstro, d as renderComponent } from '../chunks/astro/server_DrnzQWw3.mjs';
import 'kleur/colors';
import { $ as $$BaseLayout } from '../chunks/BaseLayout_Bc2tHXHa.mjs';
import 'clsx';
import { i as isAdminAuthenticated } from '../chunks/adminAuth_CY4OwU1a.mjs';
import { r as readCms } from '../chunks/cms_CRTVymfB.mjs';
export { renderers } from '../renderers.mjs';
const $$Astro$1 = createAstro();
const $$AdminPager = createComponent(($$result, $$props, $$slots) => {
const Astro2 = $$result.createAstro($$Astro$1, $$props, $$slots);
Astro2.self = $$AdminPager;
const { currentPage, totalPages, tab, pageParam } = Astro2.props;
const href = (page) => `/admin/?tab=${tab}&${pageParam}=${page}`;
const pages = Array.from({ length: totalPages }, (_, index) => index + 1);
const previousPage = Math.max(1, currentPage - 1);
const nextPage = Math.min(totalPages, currentPage + 1);
return renderTemplate`${totalPages > 1 && renderTemplate`${maybeRenderHead()}<nav class="flex flex-wrap items-center justify-center gap-1.5 mt-6" aria-label="صفحه‌بندی"><a${addAttribute(href(previousPage), "href")}${addAttribute(currentPage === 1 ? "true" : void 0, "aria-disabled")}${addAttribute([
"px-3 h-8 rounded-lg border border-gray-200 bg-white flex items-center text-xs font-bold",
currentPage === 1 ? "opacity-40 pointer-events-none" : "hover:bg-brand hover:text-white hover:border-brand"
], "class:list")}>
قبلی
</a>${pages.map((page) => renderTemplate`<a${addAttribute(href(page), "href")}${addAttribute(page === currentPage ? "page" : void 0, "aria-current")}${addAttribute([
"w-8 h-8 rounded-lg border flex items-center justify-center text-xs font-bold transition-colors",
page === currentPage ? "bg-brand text-white border-brand" : "bg-white border-gray-200 hover:bg-gray-50"
], "class:list")}>${page}</a>`)}<a${addAttribute(href(nextPage), "href")}${addAttribute(currentPage === totalPages ? "true" : void 0, "aria-disabled")}${addAttribute([
"px-3 h-8 rounded-lg border border-gray-200 bg-white flex items-center text-xs font-bold",
currentPage === totalPages ? "opacity-40 pointer-events-none" : "hover:bg-brand hover:text-white hover:border-brand"
], "class:list")}>
بعدی
</a></nav>`}`;
}, "/Users/drfelfel/ruseemrooz/src/components/admin/AdminPager.astro", void 0);
const $$Astro = createAstro();
const $$Index = createComponent(async ($$result, $$props, $$slots) => {
const Astro2 = $$result.createAstro($$Astro, $$props, $$slots);
Astro2.self = $$Index;
if (!isAdminAuthenticated(Astro2)) {
return Astro2.redirect("/admin/login/");
}
const PAGE_SIZE = 8;
const cms = await readCms();
const approvedPosts = cms.posts.filter((post) => post.status === "approved");
const pendingPosts = cms.posts.filter((post) => post.status === "pending");
const tassMemoryCount = cms.settings.agents?.tass?.processedLinks?.length ?? 0;
const saved = Astro2.url.searchParams.has("saved");
const deleteError = Astro2.url.searchParams.has("deleteError");
const editSlug = Astro2.url.searchParams.get("edit");
const editingPost = cms.posts.find((post) => post.slug === editSlug);
const postForForm = editingPost ?? {
slug: "",
title: "",
category: cms.categories[0] ?? "",
time: "\u0647\u0645\u200C\u0627\u06A9\u0646\u0648\u0646",
readTime: "\u06F3 \u062F\u0642\u06CC\u0642\u0647",
excerpt: "",
status: "pending",
body: [],
image: "",
thumbnail: "",
urgent: false,
sidebar: false
};
const selectedImage = postForForm.image || "";
const selectedThumbnail = postForForm.thumbnail || selectedImage;
const activeTab = Astro2.url.searchParams.get("tab") === "approved" ? "approved" : "pending";
const totalPagesFor = (items) => Math.max(1, Math.ceil(items.length / PAGE_SIZE));
const clampPage = (param, total) => {
const parsed = Number(Astro2.url.searchParams.get(param) ?? "1");
return Math.min(Math.max(1, Number.isFinite(parsed) ? parsed : 1), total);
};
const pendingTotalPages = totalPagesFor(pendingPosts);
const approvedTotalPages = totalPagesFor(approvedPosts);
const pendingPage = clampPage("pendingPage", pendingTotalPages);
const approvedPage = clampPage("approvedPage", approvedTotalPages);
const pendingSlice = pendingPosts.slice((pendingPage - 1) * PAGE_SIZE, pendingPage * PAGE_SIZE);
const approvedSlice = approvedPosts.slice((approvedPage - 1) * PAGE_SIZE, approvedPage * PAGE_SIZE);
const tabClass = (id) => [
"px-4 h-9 rounded-lg border text-xs font-bold transition-colors",
id === activeTab ? "bg-brand text-white border-brand" : "bg-white text-gray-700 border-gray-200 hover:bg-gray-50"
].join(" ");
return renderTemplate`${renderComponent($$result, "BaseLayout", $$BaseLayout, { "title": "\u067E\u0646\u0644 \u0627\u062F\u0645\u06CC\u0646 | \u0631\u0648\u0633 \u0627\u0645\u0631\u0648\u0632" }, { "default": async ($$result2) => renderTemplate` ${maybeRenderHead()}<main class="max-w-7xl mx-auto px-4 lg:px-8 py-8"> <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-6"> <div> <span class="text-brand text-sm font-bold">مدیریت محتوا</span> <h1 class="text-2xl font-black mt-1">پنل سبک روس امروز</h1> <p class="text-gray-500 text-sm mt-2">تایید نوشتههای AI، مدیریت دستهها، خبر فوری، آگهی و چیدمان صفحه اول</p> </div> <form action="/api/admin/logout" method="post"> <button class="bg-gray-900 text-white text-sm px-4 py-2 rounded-xl">خروج</button> </form> </div> ${saved && renderTemplate`<p class="bg-green-50 text-green-700 text-sm rounded-xl px-4 py-3 mb-5">تغییرات ذخیره شد.</p>`} ${deleteError && renderTemplate`<p class="bg-red-50 text-brand text-sm rounded-xl px-4 py-3 mb-5">برای حذف باید دقیقاً confirm را وارد کنید.</p>`} <div class="grid grid-cols-1 lg:grid-cols-3 gap-6"> <section class="lg:col-span-2 space-y-6"> <div class="bg-white rounded-2xl shadow-sm p-5"> <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3"> <div> <h2 class="font-bold text-lg">مدیریت حذف اخبار</h2> <p class="text-sm text-gray-500 mt-1">حذف همه اخبار نیاز به تایپ \`confirm\` دارد و قابل بازگشت نیست.</p> </div> <form action="/api/admin/save" method="post" data-confirm-form data-confirm-message="برای حذف همه اخبار عبارت confirm را تایپ کنید."> <input type="hidden" name="action" value="delete-all-posts"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="confirm" value="" data-confirm-input> <button class="bg-red-600 text-white text-sm px-4 py-2 rounded-xl">حذف همه اخبار</button> </form> </div> </div> <div class="bg-white rounded-2xl shadow-sm p-5"> <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-4"> <h2 class="font-bold text-lg">مدیریت نوشتهها</h2> <nav${addAttribute(activeTab, "data-active-tab")} class="flex gap-2" aria-label="تب نوشتهها"> <a href="/admin/?tab=pending" data-tab="pending"${addAttribute(tabClass("pending"), "class")}>تایید نشده (${pendingPosts.length})</a> <a href="/admin/?tab=approved" data-tab="approved"${addAttribute(tabClass("approved"), "class")}>تایید شده (${approvedPosts.length})</a> </nav> </div> <div data-panel="pending"${addAttribute(["space-y-3", { hidden: activeTab !== "pending" }], "class:list")}> ${pendingSlice.length === 0 && renderTemplate`<p class="text-sm text-gray-400">نوشته تایید نشدهای وجود ندارد.</p>`} ${pendingSlice.map((post) => renderTemplate`<article class="border border-gray-100 rounded-xl p-4"> <div class="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3"> <div> <span class="text-xs text-brand font-bold">${post.category}</span> <h3 class="font-bold mt-1">${post.title}</h3> <p class="text-sm text-gray-500 mt-1 line-clamp-2">${post.excerpt}</p> </div> <div class="flex gap-2 flex-shrink-0"> <a${addAttribute(`/admin/?tab=${activeTab}&edit=${post.slug}`, "href")} class="bg-gray-100 text-gray-700 text-xs px-3 py-2 rounded-lg">ویرایش</a> <form action="/api/admin/save" method="post" data-confirm-form${addAttribute(`\u0628\u0631\u0627\u06CC \u062D\u0630\u0641 \xAB${post.title}\xBB \u0639\u0628\u0627\u0631\u062A confirm \u0631\u0627 \u062A\u0627\u06CC\u067E \u06A9\u0646\u06CC\u062F.`, "data-confirm-message")}> <input type="hidden" name="action" value="delete-post"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <input type="hidden" name="confirm" value="" data-confirm-input> <button class="bg-red-50 text-brand text-xs px-3 py-2 rounded-lg">حذف</button> </form> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="post-status"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <input type="hidden" name="status" value="approved"> <button class="bg-green-600 text-white text-xs px-3 py-2 rounded-lg">تایید</button> </form> </div> </div> </article>`)} ${renderComponent($$result2, "AdminPager", $$AdminPager, { "currentPage": pendingPage, "totalPages": pendingTotalPages, "tab": "pending", "pageParam": "pendingPage" })} </div> <div data-panel="approved"${addAttribute(["space-y-3", { hidden: activeTab !== "approved" }], "class:list")}> ${approvedSlice.length === 0 && renderTemplate`<p class="text-sm text-gray-400">نوشته تایید شدهای وجود ندارد.</p>`} ${approvedSlice.map((post) => renderTemplate`<article class="border border-gray-100 rounded-xl p-4"> <div class="flex flex-col gap-3"> <div> <div class="flex flex-wrap items-center gap-2"> <span class="text-xs text-brand font-bold">${post.category}</span> ${post.urgent && renderTemplate`<span class="bg-red-50 text-brand text-xs px-2 py-1 rounded-full">فوری</span>`} ${post.sidebar && renderTemplate`<span class="bg-blue-50 text-blue-700 text-xs px-2 py-1 rounded-full">پنل کناری</span>`} ${(cms.settings.breakingNews.postSlugs ?? []).includes(post.slug) && renderTemplate`<span class="bg-yellow-50 text-yellow-700 text-xs px-2 py-1 rounded-full">نوار بالایی</span>`} ${cms.settings.homeLayout.featuredSlug === post.slug && renderTemplate`<span class="bg-green-50 text-green-700 text-xs px-2 py-1 rounded-full">خبر اصلی</span>`} </div> <h3 class="font-bold mt-2">${post.title}</h3> </div> <div class="flex flex-wrap gap-2"> <a${addAttribute(`/admin/?tab=${activeTab}&edit=${post.slug}`, "href")} class="bg-gray-100 text-gray-700 text-xs px-3 py-2 rounded-lg">ویرایش</a> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="post-status"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <input type="hidden" name="status" value="pending"> <button class="bg-red-50 text-brand text-xs px-3 py-2 rounded-lg">برداشتن تایید</button> </form> <form action="/api/admin/save" method="post" data-confirm-form${addAttribute(`\u0628\u0631\u0627\u06CC \u062D\u0630\u0641 \xAB${post.title}\xBB \u0639\u0628\u0627\u0631\u062A confirm \u0631\u0627 \u062A\u0627\u06CC\u067E \u06A9\u0646\u06CC\u062F.`, "data-confirm-message")}> <input type="hidden" name="action" value="delete-post"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <input type="hidden" name="confirm" value="" data-confirm-input> <button class="bg-red-50 text-brand text-xs px-3 py-2 rounded-lg">حذف</button> </form> </div> <div class="flex flex-wrap gap-2"> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="toggle-post-flag"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <input type="hidden" name="flag" value="urgent"> <button${addAttribute(["text-xs px-3 py-2 rounded-lg", post.urgent ? "bg-brand text-white" : "bg-red-50 text-brand"], "class:list")}>${post.urgent ? "\u0628\u0631\u062F\u0627\u0634\u062A\u0646 \u0641\u0648\u0631\u06CC" : "\u0641\u0648\u0631\u06CC \u06A9\u0646"}</button> </form> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="toggle-post-flag"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <input type="hidden" name="flag" value="sidebar"> <button${addAttribute(["text-xs px-3 py-2 rounded-lg", post.sidebar ? "bg-blue-600 text-white" : "bg-blue-50 text-blue-700"], "class:list")}>${post.sidebar ? "\u062D\u0630\u0641 \u0627\u0632 \u067E\u0646\u0644 \u06A9\u0646\u0627\u0631\u06CC" : "\u0627\u0641\u0632\u0648\u062F\u0646 \u0628\u0647 \u067E\u0646\u0644 \u06A9\u0646\u0627\u0631\u06CC"}</button> </form> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="set-breaking-post"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <button class="bg-yellow-50 text-yellow-700 text-xs px-3 py-2 rounded-lg">متن فوری بالا</button> </form> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="set-home-featured"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <input type="hidden" name="slug"${addAttribute(post.slug, "value")}> <button class="bg-green-50 text-green-700 text-xs px-3 py-2 rounded-lg">خبر اصلی صفحه اول</button> </form> </div> </div> </article>`)} ${renderComponent($$result2, "AdminPager", $$AdminPager, { "currentPage": approvedPage, "totalPages": approvedTotalPages, "tab": "approved", "pageParam": "approvedPage" })} </div> </div> </section> <aside class="space-y-6"> <div class="bg-white rounded-2xl shadow-sm p-5 space-y-3"> <h2 class="font-bold text-lg">Agent خبرخوان TASS</h2> <p class="text-xs text-gray-500 leading-6">RSS را میخواند، متن و تصویر خبر را استخراج میکند، با OpenAI-compatible API ترجمه میکند و پست را در وضعیت تایید نشده میسازد.</p> <p class="text-xs text-gray-400">حافظه فعلی: ${tassMemoryCount} لینک پردازششده</p> <button id="run-tass-agent" class="w-full bg-brand text-white rounded-xl py-3 font-bold">اجرای agent و ساخت پست</button> <div class="grid grid-cols-2 gap-2"> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="clear-tass-memory"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <button class="w-full bg-gray-100 text-gray-700 rounded-xl py-2 text-sm font-bold">خالی کردن حافظه</button> </form> <form action="/api/admin/save" method="post"> <input type="hidden" name="action" value="fill-tass-memory"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <button class="w-full bg-gray-100 text-gray-700 rounded-xl py-2 text-sm font-bold">پر کردن از RSS فعلی</button> </form> </div> <pre id="tass-agent-result" class="hidden bg-gray-900 text-white text-xs rounded-xl p-3 overflow-auto whitespace-pre-wrap"></pre> </div> <form action="/api/admin/save" method="post" class="bg-white rounded-2xl shadow-sm p-5 space-y-3"> <input type="hidden" name="action" value="save-post"> <input type="hidden" name="originalSlug"${addAttribute(editingPost?.slug ?? "", "value")}> <h2 class="font-bold text-lg">${editingPost ? "\u0648\u06CC\u0631\u0627\u06CC\u0634 \u0646\u0648\u0634\u062A\u0647" : "\u0627\u0641\u0632\u0648\u062F\u0646 \u0646\u0648\u0634\u062A\u0647"}</h2> <label class="block text-sm font-bold">عنوان<input name="title"${addAttribute(postForForm.title, "value")} required class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="block text-sm font-bold">اسلاگ<input name="slug"${addAttribute(postForForm.slug, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="block text-sm font-bold">دستهبندی<select name="category" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${cms.categories.map((category) => renderTemplate`<option${addAttribute(category, "value")}${addAttribute(category === postForForm.category, "selected")}>${category}</option>`)}</select></label> <div class="grid grid-cols-2 gap-2"> <label class="block text-sm font-bold">زمان<input name="time"${addAttribute(postForForm.time, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="block text-sm font-bold">مدت مطالعه<input name="readTime"${addAttribute(postForForm.readTime, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> </div> <label class="block text-sm font-bold">وضعیت<select name="status" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"><option value="pending"${addAttribute(postForForm.status === "pending", "selected")}>تایید نشده</option><option value="approved"${addAttribute(postForForm.status === "approved", "selected")}>تایید شده</option></select></label> <div class="grid grid-cols-2 gap-2"> <label class="flex items-center gap-2 text-sm font-bold bg-gray-50 rounded-xl px-3 py-2"><input type="checkbox" name="urgent"${addAttribute(postForForm.urgent, "checked")}> فوری</label> <label class="flex items-center gap-2 text-sm font-bold bg-gray-50 rounded-xl px-3 py-2"><input type="checkbox" name="sidebar"${addAttribute(postForForm.sidebar, "checked")}> پنل کناری</label> </div> <div class="border border-gray-100 rounded-xl p-3 space-y-3"> <div class="flex items-center justify-between gap-2"> <span class="text-sm font-bold">تصویر شاخص</span> <button type="button"${addAttribute(selectedImage, "data-insert-image")}${addAttribute(!selectedImage, "disabled")} class="bg-gray-100 text-gray-700 text-xs px-3 py-2 rounded-lg disabled:opacity-40">درج داخل متن</button> </div> <div id="new-image-preview" class="w-full h-36 rounded-xl bg-gray-100 flex items-center justify-center overflow-hidden"> ${selectedThumbnail ? renderTemplate`<img${addAttribute(selectedThumbnail, "src")} alt="" class="w-full h-full object-cover">` : renderTemplate`<span class="text-gray-400 text-sm">تصویری انتخاب نشده</span>`} </div> <p id="upload-status" class="text-xs rounded-lg px-2.5 py-1 text-gray-400">تصویری انتخاب نشده</p> <div class="flex flex-col sm:flex-row gap-2"> <input id="new-image-file" type="file" accept="image/*" class="w-full bg-gray-100 rounded-xl px-3 py-2 text-sm"> <button id="new-upload-btn" type="button" class="bg-gray-900 text-white rounded-xl px-4 py-2 text-sm font-bold sm:flex-shrink-0">آپلود و ساخت thumbnail</button> </div> <input id="new-image-field" name="image"${addAttribute(selectedImage, "value")} placeholder="/uploads/image.webp" class="w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand text-sm"> <input id="new-thumb-field" name="thumbnail"${addAttribute(selectedThumbnail, "value")} placeholder="/uploads/thumbs/image-thumb.webp" class="w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand text-sm"> </div> <label class="block text-sm font-bold">خلاصه<textarea name="excerpt" rows="3" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${postForForm.excerpt}</textarea></label> <label class="block text-sm font-bold">
متن
<div class="flex flex-wrap gap-2 mt-2 mb-2"> <button type="button" data-editor-command="heading" class="bg-gray-100 text-gray-700 text-xs px-3 py-2 rounded-lg">تیتر</button> <button type="button" data-editor-command="quote" class="bg-gray-100 text-gray-700 text-xs px-3 py-2 rounded-lg">نقلقول</button> <button type="button" data-editor-command="separator" class="bg-gray-100 text-gray-700 text-xs px-3 py-2 rounded-lg">جداکننده</button> <button type="button"${addAttribute(selectedImage, "data-insert-image")}${addAttribute(!selectedImage, "disabled")} class="bg-red-50 text-brand text-xs px-3 py-2 rounded-lg disabled:opacity-40">درج تصویر آپلودشده</button> </div> <textarea id="post-body-editor" name="body" rows="12" class="w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand leading-7 font-mono text-sm">${postForForm.body.join("\n\n")}</textarea> <span class="block text-xs text-gray-400 mt-2">برای تصویر داخل متن از \`[image:/uploads/example.webp|توضیح تصویر]\` استفاده میشود.</span> </label> <button class="w-full bg-brand text-white rounded-xl py-3 font-bold">ذخیره نوشته</button> </form> <form action="/api/admin/save" method="post" class="bg-white rounded-2xl shadow-sm p-5 space-y-3"> <input type="hidden" name="action" value="categories"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <h2 class="font-bold text-lg">دستهبندیها</h2> <textarea name="categories" rows="5" class="w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${cms.categories.join("\n")}</textarea> <button class="w-full bg-gray-900 text-white rounded-xl py-3 font-bold">ذخیره دستهها</button> </form> <form action="/api/admin/save" method="post" class="bg-white rounded-2xl shadow-sm p-5 space-y-3"> <input type="hidden" name="action" value="settings"> <input type="hidden" name="tab"${addAttribute(activeTab, "value")}> <h2 class="font-bold text-lg">صفحه اول و آگهی</h2> <label class="block text-sm font-bold">برچسب فوری<input name="breakingLabel"${addAttribute(cms.settings.breakingNews.label, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="block text-sm font-bold">لینک فوری<input name="breakingHref"${addAttribute(cms.settings.breakingNews.href, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="block text-sm font-bold">متنهای فوری<textarea name="breakingItems" rows="4" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${cms.settings.breakingNews.items.join("\n")}</textarea></label> <label class="block text-sm font-bold">اسلاگ پستهای نوار فوری<textarea name="breakingPostSlugs" rows="3" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${(cms.settings.breakingNews.postSlugs ?? []).join("\n")}</textarea></label> <label class="block text-sm font-bold">موضوعات داغ<textarea name="hotTopics" rows="4" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${cms.settings.hotTopics.join("\n")}</textarea></label> <label class="block text-sm font-bold">خبر اصلی<select name="featuredSlug" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${approvedPosts.map((post) => renderTemplate`<option${addAttribute(post.slug, "value")}${addAttribute(post.slug === cms.settings.homeLayout.featuredSlug, "selected")}>${post.title}</option>`)}</select></label> <label class="block text-sm font-bold">دو خبر کناری<textarea name="sideFeaturedSlugs" rows="3" class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand">${cms.settings.homeLayout.sideFeaturedSlugs.join("\n")}</textarea></label> <label class="block text-sm font-bold">تعداد آخرین اخبار<input name="latestCount" type="number" min="1"${addAttribute(cms.settings.homeLayout.latestCount, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="flex items-center gap-2 text-sm font-bold"><input type="checkbox" name="showAd"${addAttribute(cms.settings.homeLayout.showAd, "checked")}> نمایش جایگاه آگهی</label> <label class="flex items-center gap-2 text-sm font-bold"><input type="checkbox" name="adEnabled"${addAttribute(cms.settings.ad.enabled, "checked")}> آگهی فعال</label> <label class="block text-sm font-bold">عنوان آگهی<input name="adLabel"${addAttribute(cms.settings.ad.label, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="block text-sm font-bold">لینک آگهی<input name="adHref"${addAttribute(cms.settings.ad.href, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <label class="block text-sm font-bold">متن آگهی<input name="adText"${addAttribute(cms.settings.ad.text, "value")} class="mt-2 w-full bg-gray-100 rounded-xl px-3 py-2 outline-none focus:ring-1 focus:ring-brand"></label> <button class="w-full bg-brand text-white rounded-xl py-3 font-bold">ذخیره تنظیمات</button> </form> <div class="bg-white rounded-2xl shadow-sm p-5 space-y-3"> <h2 class="font-bold text-lg">API انتشار برای n8n</h2> <p class="text-xs text-gray-500 leading-6">POST به \`/api/posts/publish\` با هدر \`Authorization: Bearer ADMIN_API_TOKEN\`.</p> <code class="block bg-gray-100 text-xs rounded-xl p-3 leading-6 overflow-auto">${JSON.stringify({ title: "\u0639\u0646\u0648\u0627\u0646", category: "\u0628\u06CC\u0646\u200C\u0627\u0644\u0645\u0644\u0644", body: ["\u067E\u0627\u0631\u0627\u06AF\u0631\u0627\u0641 \u0627\u0648\u0644"], imageUrl: "https://..." })}</code> </div> </aside> </div> </main> ` })} `;
}, "/Users/drfelfel/ruseemrooz/src/pages/admin/index.astro", void 0);
const $$file = "/Users/drfelfel/ruseemrooz/src/pages/admin/index.astro";
const $$url = "/admin";
const _page = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
__proto__: null,
default: $$Index,
file: $$file,
url: $$url
}, Symbol.toStringTag, { value: 'Module' }));
const page = () => _page;
export { page };