diff --git a/app.js b/app.js
index 0afda91..18aba8a 100644
--- a/app.js
+++ b/app.js
@@ -295,7 +295,7 @@
if (!imageUrl) return; // Upload failed
}
- const { data, error } = await supabase
+ const { data: postData, error } = await supabase
.from('posts')
.insert([
{
@@ -304,10 +304,19 @@
image_url: imageUrl
}
])
- .select()
- .single();
+ .select();
if (error) throw error;
+ if (!postData || postData.length === 0) {
+ throw new Error("Failed to create post.");
+ }
+ const post = postData[0];
+
+ // Extract and add hashtags
+ const hashtags = extractHashtags(content);
+ if (hashtags.length > 0) {
+ await addHashtagsToPost(post.id, hashtags);
+ }
// Reset form
document.getElementById('postContent').value = '';
@@ -332,7 +341,8 @@
*,
profiles!posts_user_id_fkey (*),
likes (*),
- comments (count)
+ comments (count),
+ bookmarks (*)
`)
.order('created_at', { ascending: false });
@@ -387,9 +397,87 @@
}
function searchHashtag(hashtag) {
- const searchInput = document.getElementById('searchInputModal');
- searchInput.value = `#${hashtag}`;
- handleSearch();
+ // No need to use the search modal, just load the posts directly
+ loadPostsByHashtag(hashtag);
+ }
+
+ async function loadPostsByHashtag(hashtag) {
+ try {
+ document.getElementById('feedTitle').textContent = `#${hashtag}`;
+
+ const { data, error } = await supabase
+ .from('posts')
+ .select(`
+ *,
+ profiles!posts_user_id_fkey (*),
+ likes (*),
+ comments (count),
+ post_hashtags!inner(hashtags!inner(name))
+ `)
+ .eq('post_hashtags.hashtags.name', hashtag)
+ .order('created_at', { ascending: false });
+
+ if (error) throw error;
+
+ posts = data || [];
+ renderPosts();
+ closeSearch(); // Close search modal after clicking a hashtag
+
+ } catch (error) {
+ console.error('Error loading posts by hashtag:', error);
+ showNotification(`Gagal memuat zen untuk #${hashtag}`, 'error');
+ }
+ }
+
+ function extractHashtags(content) {
+ const regex = /#(\w+)/g;
+ const matches = content.match(regex);
+ if (matches) {
+ // Return unique hashtags without the '#' symbol
+ return [...new Set(matches.map(tag => tag.substring(1)))];
+ }
+ return [];
+ }
+
+ async function addHashtagsToPost(postId, hashtags) {
+ try {
+ // 1. Find existing hashtags or create new ones
+ const { data: existingHashtags, error: findError } = await supabase
+ .from('hashtags')
+ .select('id, name')
+ .in('name', hashtags);
+
+ if (findError) throw findError;
+
+ const existingHashtagNames = existingHashtags.map(h => h.name);
+ const newHashtagNames = hashtags.filter(h => !existingHashtagNames.includes(h));
+
+ let newHashtagIds = [];
+ if (newHashtagNames.length > 0) {
+ const { data: createdHashtags, error: createError } = await supabase
+ .from('hashtags')
+ .insert(newHashtagNames.map(name => ({ name })))
+ .select('id');
+
+ if (createError) throw createError;
+ newHashtagIds = createdHashtags.map(h => h.id);
+ }
+
+ const allHashtagIds = [...existingHashtags.map(h => h.id), ...newHashtagIds];
+
+ // 2. Link hashtags to the post in the join table
+ const links = allHashtagIds.map(hashtagId => ({
+ post_id: postId,
+ hashtag_id: hashtagId
+ }));
+
+ const { error: linkError } = await supabase.from('post_hashtags').insert(links);
+ if (linkError) throw linkError;
+
+ } catch (error) {
+ console.error('Error adding hashtags:', error);
+ // We don't show a notification here to not bother the user for a background task.
+ }
}
function createPostElement(post) {
@@ -399,6 +487,7 @@
const timeAgo = getTimeAgo(new Date(post.created_at));
const isLiked = post.likes && post.likes.some(like => like.user_id === currentUser?.id);
+ const isBookmarked = post.bookmarks && post.bookmarks.some(bookmark => bookmark.user_id === currentUser?.id);
const verifiedBadge = getVerifiedBadge(post.profiles.username);
div.innerHTML = `
@@ -440,9 +529,9 @@
Bagikan Tautan Postingan
-