AccountDeletePostV1

This commit is contained in:
2026-01-29 16:41:37 +11:00
parent 36ff34c893
commit bcd6d7c0ef
3 changed files with 248 additions and 26 deletions

146
script.js
View File

@@ -68,7 +68,7 @@ document.addEventListener('DOMContentLoaded', () => {
// --- QUERY SELECTORS ---
const loginForm = document.querySelector('.login-form');
const loginContainer = document.querySelector('.login-container');
const loginView = document.getElementById('login-view');
const feedView = document.getElementById('feed-view');
const emailInput = document.getElementById('email');
const passwordInput = document.getElementById('password');
@@ -80,6 +80,18 @@ document.addEventListener('DOMContentLoaded', () => {
const title = document.querySelector('.brand-section h1');
const subtitle = document.querySelector('.brand-section p');
// Onboarding Elements
const verificationView = document.getElementById('verification-view');
const onboardingView = document.getElementById('onboarding-view');
const otpInput = document.getElementById('otp-input');
const verifyBtn = document.getElementById('verify-btn');
const displayNameInput = document.getElementById('display-name');
const bioInput = document.getElementById('bio-input');
const avatarInput = document.getElementById('avatar-input');
const avatarPreview = document.getElementById('avatar-preview');
const avatarTrigger = document.getElementById('avatar-upload-trigger');
const completeSetupBtn = document.getElementById('complete-setup-btn');
// Post Creation Elements
const createPostView = document.getElementById('create-post-view');
const cancelPostBtn = document.getElementById('cancel-post-btn');
@@ -95,9 +107,71 @@ document.addEventListener('DOMContentLoaded', () => {
const lightboxView = document.getElementById('lightbox-view');
const lightboxClose = document.getElementById('lightbox-close');
const lightboxCarousel = document.querySelector('.lightbox-carousel');
// We check for counter inside helper, as it might be common class
let isLoginMode = true;
let pendingUser = null;
let generatedOTP = null;
let newAvatarBase64 = null;
// --- ONBOARDING LOGIC ---
// Avatar Upload Handler
if (avatarTrigger && avatarInput) {
avatarTrigger.addEventListener('click', () => avatarInput.click());
avatarInput.addEventListener('change', (e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
newAvatarBase64 = e.target.result;
avatarPreview.src = newAvatarBase64;
};
reader.readAsDataURL(file);
}
});
}
// Verify OTP Handler
if (verifyBtn) {
verifyBtn.addEventListener('click', () => {
if (otpInput.value === generatedOTP) {
verificationView.classList.add('hidden');
onboardingView.classList.remove('hidden');
onboardingView.classList.add('fade-in');
} else {
alert('Invalid Code');
}
});
}
// Complete Setup Handler
if (completeSetupBtn) {
completeSetupBtn.addEventListener('click', async () => {
const name = displayNameInput.value.trim();
if (!name) { alert('Name is required'); return; }
const bio = bioInput.value.trim();
// Finalize User
const finalUser = {
...pendingUser,
username: name,
bio: bio,
avatar: newAvatarBase64 || 'https://i.pravatar.cc/150?img=12'
};
// Save to DB
const existingUsers = JSON.parse(localStorage.getItem('socialAppUsers') || '[]');
existingUsers.push(finalUser);
localStorage.setItem('socialAppUsers', JSON.stringify(existingUsers));
localStorage.setItem('currentUser', JSON.stringify(finalUser)); // Log them in
// Transition
onboardingView.classList.add('hidden');
feedView.classList.remove('hidden');
feedView.classList.add('fade-in');
initFeed();
});
}
// --- LIGHTBOX LOGIC ---
function openLightbox(media, startIndex) {
@@ -120,7 +194,6 @@ document.addEventListener('DOMContentLoaded', () => {
// Scroll to index
const width = window.innerWidth;
// Need brief timeout for layout to stabilise
setTimeout(() => {
lightboxCarousel.scrollLeft = width * startIndex;
}, 10);
@@ -208,11 +281,11 @@ document.addEventListener('DOMContentLoaded', () => {
}
function navigateToFeed() {
if (loginContainer && feedView) {
loginContainer.style.opacity = '0';
if (loginView && feedView) {
loginView.style.opacity = '0';
setTimeout(() => {
loginContainer.classList.add('hidden');
loginContainer.style.display = 'none';
loginView.classList.add('hidden');
loginView.style.display = 'none';
feedView.classList.remove('hidden');
void feedView.offsetWidth;
feedView.classList.add('fade-in');
@@ -234,6 +307,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (isLoginMode) {
const user = existingUsers.find(u => u.email === email && u.password === password);
if (user) {
localStorage.setItem('currentUser', JSON.stringify(user));
showFeedback(true, 'Success!');
setTimeout(navigateToFeed, 1000);
} else {
@@ -248,11 +322,16 @@ document.addEventListener('DOMContentLoaded', () => {
showFeedback(false, 'Passwords do not match');
return;
}
const newUser = { email, password, joinedAt: timestamp };
existingUsers.push(newUser);
localStorage.setItem('socialAppUsers', JSON.stringify(existingUsers));
showFeedback(true, 'Account Created!');
setTimeout(() => { isLoginMode = true; updateUI(); setTimeout(navigateToFeed, 1000); }, 1500);
// Start Verification Flow
pendingUser = { email, password, joinedAt: timestamp };
generatedOTP = Math.floor(100000 + Math.random() * 900000).toString();
alert(`[MOCK EMAIL] Your verification code is: ${generatedOTP}`);
loginView.classList.add('hidden');
verificationView.classList.remove('hidden');
verificationView.classList.add('fade-in');
}
});
}
@@ -270,7 +349,6 @@ document.addEventListener('DOMContentLoaded', () => {
for (const post of postsToRender) {
if (!isPostDeleted(post.id) && !document.querySelector(`[data-post-id="${post.id}"]`)) {
let mediaItems = post.media;
// Backwards Compatibility implementation
if (!mediaItems && post.imageSrc) {
mediaItems = [{ type: 'image', src: post.imageSrc }];
}
@@ -323,13 +401,16 @@ document.addEventListener('DOMContentLoaded', () => {
function renderPost(post, prepend = false) {
if (document.querySelector(`[data-post-id="${post.id}"]`)) return;
const feedContainer = document.querySelector('.feed-container');
const container = document.querySelector('.feed-container'); // Renamed variable
const article = document.createElement('article');
article.className = 'post-card';
article.setAttribute('data-post-id', post.id);
const isUserPost = post.id && post.id.startsWith('post_');
const optionsHTML = isUserPost ? `
const currentUser = JSON.parse(localStorage.getItem('currentUser') || '{}');
const isOwner = post.userEmail && post.userEmail === currentUser.email;
// Only show options if owner
const optionsHTML = isOwner ? `
<button class="icon-btn-sm options-trigger">
<svg viewBox="0 0 24 24" width="20" height="20" stroke="currentColor" fill="none" stroke-width="2"><circle cx="12" cy="12" r="1"></circle><circle cx="19" cy="12" r="1"></circle><circle cx="5" cy="12" r="1"></circle></svg>
</button>
@@ -339,7 +420,7 @@ document.addEventListener('DOMContentLoaded', () => {
Delete Post
</button>
</div>
` : `<button class="icon-btn-sm">...</button>`;
` : '';
let slidesHTML = '';
let dotsHTML = '';
@@ -370,7 +451,7 @@ document.addEventListener('DOMContentLoaded', () => {
article.innerHTML = `
<div class="post-header">
<div class="post-user">
<img src="https://i.pravatar.cc/150?img=12" alt="User" class="avatar-sm">
<img src="${post.userAvatar || 'https://i.pravatar.cc/150?img=12'}" alt="User" class="avatar-sm">
<span class="username">${post.username}</span>
</div>
${optionsHTML}
@@ -403,11 +484,11 @@ document.addEventListener('DOMContentLoaded', () => {
`;
if (prepend) {
if (!feedContainer.querySelector(`[data-post-id="${post.id}"]`)) {
feedContainer.insertBefore(article, feedContainer.firstChild);
if (!container.querySelector(`[data-post-id="${post.id}"]`)) {
container.insertBefore(article, container.firstChild);
}
}
else feedContainer.appendChild(article);
else container.appendChild(article);
// Attach Drag-to-Scroll & Lightbox Click
const carousel = article.querySelector('.media-carousel');
@@ -487,15 +568,26 @@ document.addEventListener('DOMContentLoaded', () => {
const card = deleteBtn.closest('.post-card');
const id = card.getAttribute('data-post-id');
if (id && id.startsWith('post_')) {
const userPosts = JSON.parse(localStorage.getItem('socialAppUserPosts') || '[]');
const postToDelete = userPosts.find(p => p.id === id);
const currentUser = JSON.parse(localStorage.getItem('currentUser') || '{}');
if (!postToDelete || postToDelete.userEmail !== currentUser.email) {
alert('You can only delete your own posts.');
return;
}
if (confirm('Delete this post?')) {
card.style.transition = 'opacity 0.3s, transform 0.3s';
card.style.opacity = '0';
card.style.transform = 'scale(0.9)';
setTimeout(() => card.remove(), 300);
let userPosts = JSON.parse(localStorage.getItem('socialAppUserPosts') || '[]');
userPosts = userPosts.filter(p => p.id !== id);
localStorage.setItem('socialAppUserPosts', JSON.stringify(userPosts));
const updatedPosts = userPosts.filter(p => p.id !== id);
localStorage.setItem('socialAppUserPosts', JSON.stringify(updatedPosts));
deleteImageFromDB(id);
const deletedPosts = JSON.parse(localStorage.getItem('socialAppDeletedPosts') || '[]');
if (!deletedPosts.includes(id)) {
deletedPosts.push(id);
@@ -687,12 +779,15 @@ document.addEventListener('DOMContentLoaded', () => {
const caption = captionInput.value.trim();
const id = 'post_' + Date.now();
const currentUser = JSON.parse(localStorage.getItem('currentUser') || '{}');
const displayPost = {
id,
media: stagedMedia,
caption,
timestamp: new Date().toISOString(),
username: 'you',
username: currentUser.username || 'You',
userAvatar: currentUser.avatar,
userEmail: currentUser.email, // Secure Owner ID
likes: 0
};
renderPost(displayPost, true);
@@ -703,6 +798,7 @@ document.addEventListener('DOMContentLoaded', () => {
caption,
timestamp: displayPost.timestamp,
username: displayPost.username,
userEmail: currentUser.email, // Secure Owner ID
likes: 0
};