Masaüstünden temiz PocketBase kurulumu
This commit is contained in:
261
admin.js
261
admin.js
@@ -1,194 +1,135 @@
|
|||||||
import { initializeApp } from "https://www.gstatic.com/firebasejs/12.8.0/firebase-app.js";
|
import PocketBase from 'https://cdnjs.cloudflare.com/ajax/libs/pocketbase/0.21.1/pocketbase.es.mjs';
|
||||||
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";
|
|
||||||
|
|
||||||
const firebaseConfig = {
|
// 1. PocketBase Bağlantısı
|
||||||
apiKey: "AIzaSyAdLH7HMwCMZ4lThoWGEiI5TEjfvBMXem8",
|
// 'https://pocketbase.batuhanerkek.com' kısmını kendi domaininle değiştir
|
||||||
authDomain: "batuhanerkeksite.firebaseapp.com",
|
const pb = new PocketBase('https://pocketbase.batuhanerkek.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);
|
|
||||||
|
|
||||||
const loginCard = document.getElementById("login-card");
|
const loginCard = document.getElementById("login-card");
|
||||||
const adminPanel = document.getElementById("admin-panel");
|
const adminPanel = document.getElementById("admin-panel");
|
||||||
const loginForm = document.getElementById("login-form");
|
const loginForm = document.getElementById("login-form");
|
||||||
const blogForm = document.getElementById("blog-form");
|
const blogForm = document.getElementById("blog-form");
|
||||||
const postsList = document.getElementById("posts-list");
|
|
||||||
const logoutBtn = document.getElementById("logout-btn");
|
const logoutBtn = document.getElementById("logout-btn");
|
||||||
|
const postsList = document.getElementById("posts-list");
|
||||||
const tagsInput = document.getElementById("tags-input");
|
const tagsInput = document.getElementById("tags-input");
|
||||||
const tagsList = document.getElementById("tags-list");
|
const tagsList = document.getElementById("tags-list");
|
||||||
|
|
||||||
let currentTags = [];
|
let currentTags = [];
|
||||||
const postsRef = collection(db, "posts");
|
|
||||||
|
|
||||||
const renderPosts = (posts) => {
|
// Panel Görünümünü Ayarla
|
||||||
postsList.innerHTML = "";
|
function setAuthState(isLoggedIn) {
|
||||||
|
if (isLoggedIn) {
|
||||||
if (!posts.length) {
|
loginCard.classList.add("hidden");
|
||||||
const empty = document.createElement("div");
|
adminPanel.classList.remove("hidden");
|
||||||
empty.className = "post-item";
|
loadPosts();
|
||||||
empty.textContent = "Henüz blog yazısı yok.";
|
} else {
|
||||||
postsList.appendChild(empty);
|
loginCard.classList.remove("hidden");
|
||||||
return;
|
adminPanel.classList.add("hidden");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
posts.forEach((post) => {
|
// 2. Giriş Yapma (PocketBase Auth)
|
||||||
const wrapper = document.createElement("div");
|
loginForm.addEventListener("submit", async (event) => {
|
||||||
wrapper.className = "post-item";
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const title = document.createElement("h3");
|
// 3. Çıkış Yapma
|
||||||
title.textContent = post.title;
|
logoutBtn.addEventListener("click", () => {
|
||||||
|
pb.authStore.clear();
|
||||||
|
setAuthState(false);
|
||||||
|
});
|
||||||
|
|
||||||
const meta = document.createElement("div");
|
// 4. Yeni Yazı Kaydetme
|
||||||
meta.className = "post-meta";
|
blogForm.addEventListener("submit", async (event) => {
|
||||||
const tagsLabel = post.tags?.length ? post.tags.join(", ") : "Etiket yok";
|
event.preventDefault();
|
||||||
meta.textContent = `${post.date || "-"} · ${tagsLabel}`;
|
const formData = new FormData(blogForm);
|
||||||
|
|
||||||
const summary = document.createElement("p");
|
const newPost = {
|
||||||
summary.textContent = post.summary;
|
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 actions = document.createElement("div");
|
try {
|
||||||
actions.className = "post-actions";
|
await pb.collection('posts').create(newPost);
|
||||||
|
blogForm.reset();
|
||||||
|
currentTags = [];
|
||||||
|
renderTags();
|
||||||
|
loadPosts();
|
||||||
|
alert("Yazı başarıyla kaydedildi!");
|
||||||
|
} catch (error) {
|
||||||
|
alert("Kaydedilemedi: " + error.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const removeBtn = document.createElement("button");
|
// 5. Yazıları Listeleme
|
||||||
removeBtn.className = "ghost";
|
async function loadPosts() {
|
||||||
removeBtn.type = "button";
|
try {
|
||||||
removeBtn.textContent = "Sil";
|
const records = await pb.collection('posts').getFullList({
|
||||||
removeBtn.addEventListener("click", () => {
|
sort: '-created',
|
||||||
deleteDoc(doc(db, "posts", post.id));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
actions.appendChild(removeBtn);
|
postsList.innerHTML = records.map(post => `
|
||||||
wrapper.append(title, meta, summary, actions);
|
<div class="post-item">
|
||||||
postsList.appendChild(wrapper);
|
<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 setAuthState = (isLoggedIn) => {
|
// Etiket Yönetimi
|
||||||
loginCard.classList.toggle("hidden", isLoggedIn);
|
function renderTags() {
|
||||||
adminPanel.classList.toggle("hidden", !isLoggedIn);
|
tagsList.innerHTML = currentTags.map((tag, index) => `
|
||||||
};
|
<span class="tag">${tag} <i onclick="removeTag(${index})">×</i></span>
|
||||||
|
`).join('');
|
||||||
|
}
|
||||||
|
|
||||||
const renderTags = () => {
|
window.removeTag = (index) => {
|
||||||
tagsList.innerHTML = "";
|
currentTags.splice(index, 1);
|
||||||
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);
|
|
||||||
renderTags();
|
|
||||||
});
|
|
||||||
|
|
||||||
chip.appendChild(removeBtn);
|
|
||||||
tagsList.appendChild(chip);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const addTag = (rawValue) => {
|
|
||||||
const value = rawValue.trim();
|
|
||||||
if (!value) return;
|
|
||||||
if (currentTags.includes(value)) return;
|
|
||||||
currentTags = [...currentTags, value];
|
|
||||||
renderTags();
|
renderTags();
|
||||||
};
|
};
|
||||||
|
|
||||||
tagsInput.addEventListener("keydown", (event) => {
|
tagsInput.addEventListener("keydown", (event) => {
|
||||||
if (event.key === "Enter") {
|
if (event.key === "Enter") {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
addTag(tagsInput.value);
|
const tag = tagsInput.value.trim();
|
||||||
|
if (tag && !currentTags.includes(tag)) {
|
||||||
|
currentTags.push(tag);
|
||||||
|
renderTags();
|
||||||
|
}
|
||||||
tagsInput.value = "";
|
tagsInput.value = "";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
loginForm.addEventListener("submit", (event) => {
|
// Sayfa yüklendiğinde oturum kontrolü
|
||||||
event.preventDefault();
|
if (pb.authStore.isValid) {
|
||||||
const formData = new FormData(loginForm);
|
setAuthState(true);
|
||||||
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);
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user