Masaüstünden temiz PocketBase kurulumu
This commit is contained in:
259
admin.js
259
admin.js
@@ -1,194 +1,135 @@
|
||||
import { initializeApp } from "https://www.gstatic.com/firebasejs/12.8.0/firebase-app.js";
|
||||
import { getAnalytics } from "https://www.gstatic.com/firebasejs/12.8.0/firebase-analytics.js";
|
||||
import {
|
||||
getAuth,
|
||||
onAuthStateChanged,
|
||||
signInWithEmailAndPassword,
|
||||
signOut,
|
||||
} from "https://www.gstatic.com/firebasejs/12.8.0/firebase-auth.js";
|
||||
import {
|
||||
addDoc,
|
||||
collection,
|
||||
deleteDoc,
|
||||
doc,
|
||||
getFirestore,
|
||||
onSnapshot,
|
||||
orderBy,
|
||||
query,
|
||||
serverTimestamp,
|
||||
} from "https://www.gstatic.com/firebasejs/12.8.0/firebase-firestore.js";
|
||||
import PocketBase from 'https://cdnjs.cloudflare.com/ajax/libs/pocketbase/0.21.1/pocketbase.es.mjs';
|
||||
|
||||
const firebaseConfig = {
|
||||
apiKey: "AIzaSyAdLH7HMwCMZ4lThoWGEiI5TEjfvBMXem8",
|
||||
authDomain: "batuhanerkeksite.firebaseapp.com",
|
||||
projectId: "batuhanerkeksite",
|
||||
storageBucket: "batuhanerkeksite.firebasestorage.app",
|
||||
messagingSenderId: "439489523058",
|
||||
appId: "1:439489523058:web:ce15dc3127f1ce03a8c1eb",
|
||||
measurementId: "G-FC46PNZJHX",
|
||||
};
|
||||
|
||||
const app = initializeApp(firebaseConfig);
|
||||
try {
|
||||
getAnalytics(app);
|
||||
} catch {
|
||||
// Analytics optional in local/dev environments.
|
||||
}
|
||||
|
||||
const auth = getAuth(app);
|
||||
const db = getFirestore(app);
|
||||
// 1. PocketBase Bağlantısı
|
||||
// 'https://pocketbase.batuhanerkek.com' kısmını kendi domaininle değiştir
|
||||
const pb = new PocketBase('https://pocketbase.batuhanerkek.com');
|
||||
|
||||
const loginCard = document.getElementById("login-card");
|
||||
const adminPanel = document.getElementById("admin-panel");
|
||||
const loginForm = document.getElementById("login-form");
|
||||
const blogForm = document.getElementById("blog-form");
|
||||
const postsList = document.getElementById("posts-list");
|
||||
const logoutBtn = document.getElementById("logout-btn");
|
||||
const postsList = document.getElementById("posts-list");
|
||||
const tagsInput = document.getElementById("tags-input");
|
||||
const tagsList = document.getElementById("tags-list");
|
||||
|
||||
let currentTags = [];
|
||||
const postsRef = collection(db, "posts");
|
||||
|
||||
const renderPosts = (posts) => {
|
||||
postsList.innerHTML = "";
|
||||
|
||||
if (!posts.length) {
|
||||
const empty = document.createElement("div");
|
||||
empty.className = "post-item";
|
||||
empty.textContent = "Henüz blog yazısı yok.";
|
||||
postsList.appendChild(empty);
|
||||
return;
|
||||
// Panel Görünümünü Ayarla
|
||||
function setAuthState(isLoggedIn) {
|
||||
if (isLoggedIn) {
|
||||
loginCard.classList.add("hidden");
|
||||
adminPanel.classList.remove("hidden");
|
||||
loadPosts();
|
||||
} else {
|
||||
loginCard.classList.remove("hidden");
|
||||
adminPanel.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
posts.forEach((post) => {
|
||||
const wrapper = document.createElement("div");
|
||||
wrapper.className = "post-item";
|
||||
|
||||
const title = document.createElement("h3");
|
||||
title.textContent = post.title;
|
||||
|
||||
const meta = document.createElement("div");
|
||||
meta.className = "post-meta";
|
||||
const tagsLabel = post.tags?.length ? post.tags.join(", ") : "Etiket yok";
|
||||
meta.textContent = `${post.date || "-"} · ${tagsLabel}`;
|
||||
|
||||
const summary = document.createElement("p");
|
||||
summary.textContent = post.summary;
|
||||
|
||||
const actions = document.createElement("div");
|
||||
actions.className = "post-actions";
|
||||
|
||||
const removeBtn = document.createElement("button");
|
||||
removeBtn.className = "ghost";
|
||||
removeBtn.type = "button";
|
||||
removeBtn.textContent = "Sil";
|
||||
removeBtn.addEventListener("click", () => {
|
||||
deleteDoc(doc(db, "posts", post.id));
|
||||
// 2. Giriş Yapma (PocketBase Auth)
|
||||
loginForm.addEventListener("submit", async (event) => {
|
||||
event.preventDefault();
|
||||
const formData = new FormData(loginForm);
|
||||
try {
|
||||
await pb.collection('users').authWithPassword(
|
||||
formData.get("email"),
|
||||
formData.get("password")
|
||||
);
|
||||
loginForm.reset();
|
||||
setAuthState(true);
|
||||
} catch (error) {
|
||||
alert("Giriş başarısız: " + error.message);
|
||||
}
|
||||
});
|
||||
|
||||
actions.appendChild(removeBtn);
|
||||
wrapper.append(title, meta, summary, actions);
|
||||
postsList.appendChild(wrapper);
|
||||
// 3. Çıkış Yapma
|
||||
logoutBtn.addEventListener("click", () => {
|
||||
pb.authStore.clear();
|
||||
setAuthState(false);
|
||||
});
|
||||
|
||||
// 4. Yeni Yazı Kaydetme
|
||||
blogForm.addEventListener("submit", async (event) => {
|
||||
event.preventDefault();
|
||||
const formData = new FormData(blogForm);
|
||||
|
||||
const newPost = {
|
||||
title: formData.get("title").trim(),
|
||||
tags: JSON.stringify(currentTags), // PocketBase için dizi formatı
|
||||
summary: formData.get("summary").trim(),
|
||||
content: formData.get("content").trim(),
|
||||
date: formData.get("date"),
|
||||
image: formData.get("image").trim(),
|
||||
};
|
||||
|
||||
const setAuthState = (isLoggedIn) => {
|
||||
loginCard.classList.toggle("hidden", isLoggedIn);
|
||||
adminPanel.classList.toggle("hidden", !isLoggedIn);
|
||||
};
|
||||
|
||||
const renderTags = () => {
|
||||
tagsList.innerHTML = "";
|
||||
if (!currentTags.length) return;
|
||||
|
||||
currentTags.forEach((tag, index) => {
|
||||
const chip = document.createElement("span");
|
||||
chip.className = "tag";
|
||||
chip.textContent = tag;
|
||||
|
||||
const removeBtn = document.createElement("button");
|
||||
removeBtn.type = "button";
|
||||
removeBtn.setAttribute("aria-label", `${tag} etiketini kaldır`);
|
||||
removeBtn.textContent = "×";
|
||||
removeBtn.addEventListener("click", () => {
|
||||
currentTags = currentTags.filter((_, i) => i !== index);
|
||||
try {
|
||||
await pb.collection('posts').create(newPost);
|
||||
blogForm.reset();
|
||||
currentTags = [];
|
||||
renderTags();
|
||||
loadPosts();
|
||||
alert("Yazı başarıyla kaydedildi!");
|
||||
} catch (error) {
|
||||
alert("Kaydedilemedi: " + error.message);
|
||||
}
|
||||
});
|
||||
|
||||
chip.appendChild(removeBtn);
|
||||
tagsList.appendChild(chip);
|
||||
// 5. Yazıları Listeleme
|
||||
async function loadPosts() {
|
||||
try {
|
||||
const records = await pb.collection('posts').getFullList({
|
||||
sort: '-created',
|
||||
});
|
||||
|
||||
postsList.innerHTML = records.map(post => `
|
||||
<div class="post-item">
|
||||
<span>${post.title}</span>
|
||||
<button onclick="deletePost('${post.id}')">Sil</button>
|
||||
</div>
|
||||
`).join('');
|
||||
} catch (error) {
|
||||
console.error("Yazılar yüklenemedi:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Yazı Silme Fonksiyonu (Global yapıyoruz)
|
||||
window.deletePost = async (id) => {
|
||||
if (confirm("Bu yazıyı silmek istediğinize emin misiniz?")) {
|
||||
try {
|
||||
await pb.collection('posts').delete(id);
|
||||
loadPosts();
|
||||
} catch (error) {
|
||||
alert("Silinemedi: " + error.message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const addTag = (rawValue) => {
|
||||
const value = rawValue.trim();
|
||||
if (!value) return;
|
||||
if (currentTags.includes(value)) return;
|
||||
currentTags = [...currentTags, value];
|
||||
// Etiket Yönetimi
|
||||
function renderTags() {
|
||||
tagsList.innerHTML = currentTags.map((tag, index) => `
|
||||
<span class="tag">${tag} <i onclick="removeTag(${index})">×</i></span>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
window.removeTag = (index) => {
|
||||
currentTags.splice(index, 1);
|
||||
renderTags();
|
||||
};
|
||||
|
||||
tagsInput.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault();
|
||||
addTag(tagsInput.value);
|
||||
const tag = tagsInput.value.trim();
|
||||
if (tag && !currentTags.includes(tag)) {
|
||||
currentTags.push(tag);
|
||||
renderTags();
|
||||
}
|
||||
tagsInput.value = "";
|
||||
}
|
||||
});
|
||||
|
||||
loginForm.addEventListener("submit", (event) => {
|
||||
event.preventDefault();
|
||||
const formData = new FormData(loginForm);
|
||||
const email = formData.get("email");
|
||||
const password = formData.get("password");
|
||||
|
||||
signInWithEmailAndPassword(auth, email, password)
|
||||
.then(() => {
|
||||
loginForm.reset();
|
||||
})
|
||||
.catch(() => {
|
||||
alert("Giriş başarısız. E-posta veya şifre hatalı.");
|
||||
});
|
||||
});
|
||||
|
||||
logoutBtn.addEventListener("click", () => {
|
||||
signOut(auth);
|
||||
});
|
||||
|
||||
blogForm.addEventListener("submit", (event) => {
|
||||
event.preventDefault();
|
||||
const formData = new FormData(blogForm);
|
||||
const newPost = {
|
||||
title: formData.get("title").trim(),
|
||||
tags: currentTags,
|
||||
summary: formData.get("summary").trim(),
|
||||
content: formData.get("content").trim(),
|
||||
date: formData.get("date"),
|
||||
image: formData.get("image").trim(),
|
||||
createdAt: serverTimestamp(),
|
||||
};
|
||||
|
||||
addDoc(postsRef, newPost)
|
||||
.then(() => {
|
||||
blogForm.reset();
|
||||
currentTags = [];
|
||||
renderTags();
|
||||
})
|
||||
.catch(() => {
|
||||
alert("Yazı kaydedilemedi. Tekrar deneyin.");
|
||||
});
|
||||
});
|
||||
|
||||
onAuthStateChanged(auth, (user) => {
|
||||
setAuthState(!!user);
|
||||
});
|
||||
|
||||
const postsQuery = query(postsRef, orderBy("createdAt", "desc"));
|
||||
onSnapshot(postsQuery, (snapshot) => {
|
||||
const posts = snapshot.docs.map((docSnap) => ({
|
||||
id: docSnap.id,
|
||||
...docSnap.data(),
|
||||
}));
|
||||
renderPosts(posts);
|
||||
});
|
||||
// Sayfa yüklendiğinde oturum kontrolü
|
||||
if (pb.authStore.isValid) {
|
||||
setAuthState(true);
|
||||
}
|
||||
Reference in New Issue
Block a user