From 0811c07a28d7f5fa9c09a9259d1a75475f51c044 Mon Sep 17 00:00:00 2001
From: Nunu Miah <nm01312@surrey.ac.uk>
Date: Thu, 22 May 2025 20:19:27 +0100
Subject: [PATCH 1/3] Created Social tab to search for users and a public
 profile view to follow the user and see their watchlist and fixed login to
 add the user to firestore database if they do not exist

---
 movie-group-8/src/router/index.js       |  14 ++-
 movie-group-8/src/views/Login.vue       | 119 +++++++++++++++---------
 movie-group-8/src/views/Social.vue      | 100 ++++++++++++++++++++
 movie-group-8/src/views/UserProfile.vue | 117 +++++++++++++++++++++++
 4 files changed, 305 insertions(+), 45 deletions(-)
 create mode 100644 movie-group-8/src/views/Social.vue
 create mode 100644 movie-group-8/src/views/UserProfile.vue

diff --git a/movie-group-8/src/router/index.js b/movie-group-8/src/router/index.js
index f4763b4..fcbec63 100644
--- a/movie-group-8/src/router/index.js
+++ b/movie-group-8/src/router/index.js
@@ -10,7 +10,7 @@ const router = createRouter({
         
         
         { path: '/', component: () => import('../views/Home.vue') },
-        {path: '/top-rated', component: () => import('../views/TopRated.vue'), meta: { requiresAuth: true }},
+        { path: '/top-rated', component: () => import('../views/TopRated.vue'), meta: { requiresAuth: true }},
         { path: '/register', component: () => import('../views/Register.vue') },
         { path: '/login', component: () => import('../views/Login.vue') },
         { path: '/recover-account', component: () => import('../views/RecoverAccount.vue') },
@@ -48,7 +48,17 @@ const router = createRouter({
             component: () => import('../views/Settings.vue'), 
             meta: { requiresAuth: true },
         },
-
+        {
+            path: '/social',
+            name: 'Social',
+            component: () => import('../views/Social.vue'),
+            meta: { requiresAuth: true },
+        },
+        {
+            path: '/user/:id',
+            name: 'UserProfile',
+            component: () => import('../views/UserProfile.vue')
+        },
     ],
 });
 
diff --git a/movie-group-8/src/views/Login.vue b/movie-group-8/src/views/Login.vue
index eecffe4..45657bb 100644
--- a/movie-group-8/src/views/Login.vue
+++ b/movie-group-8/src/views/Login.vue
@@ -61,47 +61,80 @@
         </div>
       </div>
     </div>
-  </template>
+</template>
   
-  <script setup>
-  import { ref } from 'vue';
-  import { getAuth, signInWithEmailAndPassword, signInWithPopup, GoogleAuthProvider } from 'firebase/auth';
-  import { useRouter } from 'vue-router';
-  
-  const email = ref('');
-  const password = ref('');
-  const router = useRouter();
-  const loading = ref(false);
-  
-  const login = async () => {
-    try {
-      loading.value = true;
-      const auth = getAuth();
-      await signInWithEmailAndPassword(auth, email.value, password.value);
-      console.log('Successfully logged in!');
-      router.push('/films');
-    } catch (error) {
-      console.error(error);
-      alert(error.message);
-    } finally {
-      loading.value = false;
-    }
-  };
-  
-  const signInWithGoogle = async () => {
-    try {
-      loading.value = true;
-      const auth = getAuth();
-      const provider = new GoogleAuthProvider();
-      await signInWithPopup(auth, provider);
-      console.log('Successfully signed in with Google!');
-      router.push('/films');
-    } catch (error) {
-      console.error(error);
-      alert(error.message);
-    } finally {
-      loading.value = false;
-    }
-  };
-  </script>
-  
\ No newline at end of file
+<script setup>
+import { ref } from 'vue';
+import {
+  getAuth,
+  signInWithEmailAndPassword,
+  signInWithPopup,
+  GoogleAuthProvider
+} from 'firebase/auth';
+import {
+  getFirestore,
+  doc,
+  getDoc,
+  setDoc
+} from 'firebase/firestore';
+import { useRouter } from 'vue-router';
+
+const email = ref('');
+const password = ref('');
+const router = useRouter();
+const loading = ref(false);
+
+const db = getFirestore();
+
+const createUserIfNotExists = async (user) => {
+  const userRef = doc(db, 'users', user.uid);
+  const userSnap = await getDoc(userRef);
+
+  if (!userSnap.exists()) {
+    await setDoc(userRef, {
+      uid: user.uid,
+      displayName: user.displayName || 'Anonymous',
+      photoURL: user.photoURL || '',
+    });
+  }
+};
+
+const login = async () => {
+  try {
+    loading.value = true;
+    const auth = getAuth();
+    const userCredential = await signInWithEmailAndPassword(auth, email.value, password.value);
+    const user = userCredential.user;
+
+    await createUserIfNotExists(user);
+
+    console.log('Successfully logged in!');
+    router.push('/films');
+  } catch (error) {
+    console.error(error);
+    alert(error.message);
+  } finally {
+    loading.value = false;
+  }
+};
+
+const signInWithGoogle = async () => {
+  try {
+    loading.value = true;
+    const auth = getAuth();
+    const provider = new GoogleAuthProvider();
+    const result = await signInWithPopup(auth, provider);
+    const user = result.user;
+
+    await createUserIfNotExists(user);
+
+    console.log('Successfully signed in with Google!');
+    router.push('/films');
+  } catch (error) {
+    console.error(error);
+    alert(error.message);
+  } finally {
+    loading.value = false;
+  }
+};
+</script>
\ No newline at end of file
diff --git a/movie-group-8/src/views/Social.vue b/movie-group-8/src/views/Social.vue
new file mode 100644
index 0000000..34bbed7
--- /dev/null
+++ b/movie-group-8/src/views/Social.vue
@@ -0,0 +1,100 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-neutral-900 p-6">
+    <h1 class="text-3xl font-bold text-gray-900 dark:text-white mb-6 text-center">Find and Follow Users</h1>
+
+    <div class="max-w-xl mx-auto mb-6">
+      <input
+        type="text"
+        v-model="searchTerm"
+        placeholder="Search by display name..."
+        class="w-full p-3 rounded-lg border border-gray-300 dark:border-neutral-700 dark:bg-neutral-800 dark:text-white"
+      />
+    </div>
+
+    <div class="grid gap-4 max-w-3xl mx-auto">
+      <div
+        v-for="user in filteredUsers"
+        :key="user.uid"
+        class="flex items-center justify-between p-4 bg-white dark:bg-neutral-800 border dark:border-neutral-700 rounded-lg"
+      >
+        <router-link :to="`/user/${user.uid}`" class="flex items-center gap-4">
+          <img
+            :src="user.photoURL || defaultAvatar"
+            class="w-12 h-12 rounded-full object-cover"
+            alt="Avatar"
+          />
+          <span class="text-lg font-semibold text-gray-800 dark:text-white">{{ user.displayName }}</span>
+        </router-link>
+        <button
+          @click="toggleFollow(user.uid)"
+          class="px-4 py-1.5 text-sm rounded-lg font-medium"
+          :class="isFollowing(user.uid)
+            ? 'bg-red-500 text-white hover:bg-red-600'
+            : 'bg-blue-600 text-white hover:bg-blue-700'"
+        >
+          {{ isFollowing(user.uid) ? 'Unfollow' : 'Follow' }}
+        </button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted } from 'vue'
+import { getAuth } from 'firebase/auth'
+import {
+  getFirestore,
+  collection,
+  getDocs,
+  setDoc,
+  deleteDoc,
+  doc
+} from 'firebase/firestore'
+
+const auth = getAuth()
+const db = getFirestore()
+const currentUser = auth.currentUser
+
+const searchTerm = ref('')
+const users = ref([])
+const following = ref([])
+const defaultAvatar = 'https://via.placeholder.com/150'
+
+onMounted(async () => {
+  await fetchUsers()
+  await fetchFollowing()
+})
+
+const fetchUsers = async () => {
+  const snapshot = await getDocs(collection(db, 'users'))
+  users.value = snapshot.docs
+    .map(doc => doc.data())
+    .filter(u => u.uid !== currentUser?.uid && !u.hidden) // exclude self and test user
+}
+
+const fetchFollowing = async () => {
+  const snapshot = await getDocs(collection(db, 'users', currentUser.uid, 'following'))
+  following.value = snapshot.docs.map(doc => doc.id)
+}
+
+const isFollowing = (uid) => following.value.includes(uid)
+
+const toggleFollow = async (uid) => {
+  const followRef = doc(db, 'users', currentUser.uid, 'following', uid)
+
+  if (isFollowing(uid)) {
+    await deleteDoc(followRef)
+    following.value = following.value.filter(id => id !== uid)
+  } else {
+    await setDoc(followRef, { followedAt: Date.now() })
+    following.value.push(uid)
+  }
+}
+
+const filteredUsers = computed(() => {
+  if (!searchTerm.value.trim()) return users.value
+  return users.value.filter(u =>
+    u.displayName.toLowerCase().includes(searchTerm.value.toLowerCase())
+  )
+})
+</script>
\ No newline at end of file
diff --git a/movie-group-8/src/views/UserProfile.vue b/movie-group-8/src/views/UserProfile.vue
new file mode 100644
index 0000000..74c0cfc
--- /dev/null
+++ b/movie-group-8/src/views/UserProfile.vue
@@ -0,0 +1,117 @@
+<template>
+  <div class="min-h-screen bg-gray-100 dark:bg-neutral-900 p-6">
+    <div class="text-center mb-10">
+      <img
+        v-if="user.photoURL"
+        :src="user.photoURL"
+        alt="Profile"
+        class="w-24 h-24 mx-auto rounded-full object-cover"
+      />
+      <h1 class="text-2xl font-bold mt-4 text-gray-800 dark:text-white">
+        {{ user.displayName || 'Unknown User' }}
+      </h1>
+
+      <button
+        v-if="!isOwnProfile"
+        @click="toggleFollow"
+        class="mt-3 px-4 py-2 rounded-lg text-white text-sm"
+        :class="isFollowing ? 'bg-red-500 hover:bg-red-600' : 'bg-blue-600 hover:bg-blue-700'"
+      >
+        {{ isFollowing ? 'Unfollow' : 'Follow' }}
+      </button>
+    </div>
+
+    <h2 class="text-xl font-semibold text-gray-800 dark:text-white mb-4 text-center">
+      Watchlist
+    </h2>
+
+    <div v-if="watchlist.length === 0" class="text-center text-gray-500 dark:text-gray-400">
+      No public watchlist found.
+    </div>
+
+    <div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
+      <router-link
+        v-for="movie in watchlist"
+        :key="movie.id"
+        :to="`/films/${movie.id}`"
+        class="block bg-white dark:bg-neutral-800 border dark:border-neutral-700 rounded-lg p-4 hover:opacity-90 transition"
+      >
+        <img
+          v-if="movie.poster_path"
+          :src="'https://image.tmdb.org/t/p/w342' + movie.poster_path"
+          alt="Poster"
+          class="w-full h-60 object-cover rounded mb-2"
+        />
+        <p class="font-semibold text-gray-800 dark:text-white">{{ movie.title }}</p>
+        <p class="text-sm text-gray-600 dark:text-neutral-400">⭐ {{ movie.vote_average }}</p>
+        <p class="text-xs text-gray-400 dark:text-neutral-500">{{ movie.status }}</p>
+      </router-link>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue'
+import { useRoute } from 'vue-router'
+import { getAuth } from 'firebase/auth'
+import {
+  getFirestore,
+  doc,
+  getDoc,
+  collection,
+  getDocs,
+  setDoc,
+  deleteDoc
+} from 'firebase/firestore'
+
+const route = useRoute()
+const db = getFirestore()
+const auth = getAuth()
+
+const profileUserId = route.params.id
+const currentUser = auth.currentUser
+
+const user = ref({})
+const watchlist = ref([])
+const isFollowing = ref(false)
+const isOwnProfile = currentUser?.uid === profileUserId
+
+onMounted(async () => {
+  await fetchUserProfile()
+  await fetchWatchlist()
+  if (!isOwnProfile) await checkIfFollowing()
+})
+
+const fetchUserProfile = async () => {
+  const docRef = doc(db, 'users', profileUserId)
+  const docSnap = await getDoc(docRef)
+  if (docSnap.exists()) {
+    user.value = docSnap.data()
+  } else {
+    user.value = { displayName: 'User Not Found' }
+  }
+}
+
+const fetchWatchlist = async () => {
+  const snapshot = await getDocs(collection(db, 'users', profileUserId, 'watchlist'))
+  watchlist.value = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }))
+}
+
+const checkIfFollowing = async () => {
+  const followRef = doc(db, 'users', currentUser.uid, 'following', profileUserId)
+  const followSnap = await getDoc(followRef)
+  isFollowing.value = followSnap.exists()
+}
+
+const toggleFollow = async () => {
+  const followRef = doc(db, 'users', currentUser.uid, 'following', profileUserId)
+
+  if (isFollowing.value) {
+    await deleteDoc(followRef)
+    isFollowing.value = false
+  } else {
+    await setDoc(followRef, { followedAt: Date.now() })
+    isFollowing.value = true
+  }
+}
+</script>
\ No newline at end of file
-- 
GitLab


From e883407ca45ad15e9a40e7bef56a54fa076a430c Mon Sep 17 00:00:00 2001
From: Nunu Miah <nm01312@surrey.ac.uk>
Date: Thu, 22 May 2025 21:35:20 +0100
Subject: [PATCH 2/3] Fixed register to add user to database and the navigation
 bar now includes the social tab, new users now have a default avatar and the
 profile view has been changed to have 3 tabs to view the users followers,
 followings and watchlist

---
 movie-group-8/src/assets/default_avatar.png | Bin 0 -> 39076 bytes
 movie-group-8/src/components/Navbar.vue     |   1 +
 movie-group-8/src/views/Login.vue           |   3 +-
 movie-group-8/src/views/Profile.vue         | 226 +++++++++++++++-----
 movie-group-8/src/views/Register.vue        |  35 ++-
 5 files changed, 207 insertions(+), 58 deletions(-)
 create mode 100644 movie-group-8/src/assets/default_avatar.png

diff --git a/movie-group-8/src/assets/default_avatar.png b/movie-group-8/src/assets/default_avatar.png
new file mode 100644
index 0000000000000000000000000000000000000000..778e051529c32dc9e845d961a9229d0addaf09ea
GIT binary patch
literal 39076
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

literal 0
HcmV?d00001

diff --git a/movie-group-8/src/components/Navbar.vue b/movie-group-8/src/components/Navbar.vue
index 7abd7a8..1a4d4d9 100644
--- a/movie-group-8/src/components/Navbar.vue
+++ b/movie-group-8/src/components/Navbar.vue
@@ -87,6 +87,7 @@ const navigation = ref([
   { name: 'Films', href: '/films', authRequired: true },
   { name: 'Watchlist', href: '/watchlist', authRequired: true },
   { name: 'Top Rated', href: '/top-rated', authRequired: true },
+  { name: 'Social', href: '/social', authRequired: true },
 
 ]);
 
diff --git a/movie-group-8/src/views/Login.vue b/movie-group-8/src/views/Login.vue
index 45657bb..909e2ed 100644
--- a/movie-group-8/src/views/Login.vue
+++ b/movie-group-8/src/views/Login.vue
@@ -78,6 +78,7 @@ import {
   setDoc
 } from 'firebase/firestore';
 import { useRouter } from 'vue-router';
+import defaultAvatar from '@/assets/default_avatar.png'
 
 const email = ref('');
 const password = ref('');
@@ -94,7 +95,7 @@ const createUserIfNotExists = async (user) => {
     await setDoc(userRef, {
       uid: user.uid,
       displayName: user.displayName || 'Anonymous',
-      photoURL: user.photoURL || '',
+      photoURL: defaultAvatar
     });
   }
 };
diff --git a/movie-group-8/src/views/Profile.vue b/movie-group-8/src/views/Profile.vue
index 733b4ee..065de78 100644
--- a/movie-group-8/src/views/Profile.vue
+++ b/movie-group-8/src/views/Profile.vue
@@ -9,7 +9,7 @@
       />
       <h1 class="text-3xl font-bold text-gray-800 dark:text-white">{{ displayName || 'Anonymous' }}</h1>
       <p class="text-sm text-gray-600 dark:text-neutral-400">{{ userEmail }}</p>
-      <p class="mt-2 text-base text-gray-600 dark:text-neutral-400">Movie fan and scene collector.</p>
+      <p class="mt-2 text-base text-gray-600 dark:text-neutral-400">{{ description }}</p>
 
       <button
         @click="showForm = !showForm"
@@ -19,6 +19,7 @@
       </button>
     </div>
 
+    <!-- Update Form -->
     <div v-if="showForm" class="max-w-xl mx-auto mb-12 bg-white dark:bg-neutral-800 p-6 rounded-xl border dark:border-neutral-700">
       <form @submit.prevent="handleUpdateProfile" class="grid gap-6">
         <div>
@@ -26,6 +27,11 @@
           <input type="text" v-model="displayName" class="w-full border border-gray-400 rounded-lg p-2 dark:text-white" required />
         </div>
 
+        <div>
+          <label class="block text-sm mb-2 dark:text-white">Description</label>
+          <textarea v-model="description" rows="3" class="w-full border border-gray-400 rounded-lg p-2 dark:text-white" />
+        </div>
+
         <div>
           <label class="block text-sm mb-2 dark:text-white">New Password</label>
           <input type="password" v-model="newPassword" class="w-full border border-gray-400 rounded-lg p-2 dark:text-white" />
@@ -43,74 +49,114 @@
       </form>
     </div>
 
-    <div>
-      <h2 class="text-2xl font-semibold text-gray-800 dark:text-white mb-6">Your Watchlist</h2>
+    <!-- Tabs -->
+    <div class="flex justify-center gap-4 mb-6">
+      <button
+        v-for="tab in ['watchlist', 'followers', 'following']"
+        :key="tab"
+        @click="activeTab = tab"
+        :class="[
+          'px-4 py-2 rounded-lg text-sm font-medium',
+          activeTab === tab
+            ? 'bg-blue-600 text-white'
+            : 'bg-white dark:bg-neutral-700 text-gray-800 dark:text-white border border-gray-300 dark:border-neutral-600'
+        ]"
+      >
+        {{ tab.charAt(0).toUpperCase() + tab.slice(1) }}
+      </button>
+    </div>
 
-      <div v-if="watchlist.length === 0" class="text-gray-500 dark:text-gray-400 text-sm">
-        Your watchlist is empty.
+    <!-- Tab Content -->
+    <div v-if="activeTab === 'watchlist'" class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
+      <router-link
+        v-for="movie in watchlist"
+        :key="movie.id"
+        :to="`/films/${movie.id}`"
+        class="block bg-white dark:bg-neutral-800 border dark:border-neutral-700 rounded-lg p-3 hover:opacity-90 transition"
+      >
+        <img
+          v-if="movie.poster_path"
+          :src="'https://image.tmdb.org/t/p/w342' + movie.poster_path"
+          alt="Poster"
+          class="w-full h-60 object-cover rounded mb-3"
+        />
+        <p class="font-semibold text-gray-800 dark:text-white">{{ movie.title }}</p>
+        <p class="text-sm text-gray-600 dark:text-neutral-400">⭐ {{ movie.vote_average }} — {{ movie.status }}</p>
+      </router-link>
+    </div>
+
+    <!-- Followers -->
+    <div v-else-if="activeTab === 'followers'" class="grid gap-4 max-w-xl mx-auto">
+      <div
+        v-for="follower in followers"
+        :key="follower.uid"
+        class="flex items-center justify-between p-4 bg-white dark:bg-neutral-800 border dark:border-neutral-700 rounded-lg"
+      >
+        <router-link :to="`/user/${follower.uid}`" class="flex items-center gap-4">
+          <img
+            :src="follower.photoURL || 'https://via.placeholder.com/150'"
+            alt="Avatar"
+            class="w-12 h-12 rounded-full object-cover"
+          />
+          <span class="text-lg font-semibold text-gray-800 dark:text-white">{{ follower.displayName }}</span>
+        </router-link>
       </div>
+    </div>
 
-      <div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
-        <div
-          v-for="movie in watchlist"
-          :key="movie.id"
-          class="bg-white dark:bg-neutral-800 border dark:border-neutral-700 rounded-lg p-3 text-left"
-        >
+    <!-- Following -->
+    <div v-else-if="activeTab === 'following'" class="grid gap-4 max-w-xl mx-auto">
+      <div
+        v-for="followed in following"
+        :key="followed.uid"
+        class="flex items-center justify-between p-4 bg-white dark:bg-neutral-800 border dark:border-neutral-700 rounded-lg"
+      >
+        <router-link :to="`/user/${followed.uid}`" class="flex items-center gap-4">
           <img
-            v-if="movie.poster_path"
-            :src="'https://image.tmdb.org/t/p/w342' + movie.poster_path"
-            alt="Poster"
-            class="w-full h-60 object-cover rounded mb-3"
+            :src="followed.photoURL || 'https://via.placeholder.com/150'"
+            alt="Avatar"
+            class="w-12 h-12 rounded-full object-cover"
           />
-          <p class="font-semibold text-gray-800 dark:text-white">{{ movie.title }}</p>
-          <p class="text-sm text-gray-600 dark:text-neutral-400">⭐ {{ movie.vote_average }} — {{ movie.status }}</p>
-        </div>
+          <span class="text-lg font-semibold text-gray-800 dark:text-white">{{ followed.displayName }}</span>
+        </router-link>
       </div>
     </div>
   </div>
 </template>
 
 <script setup>
-import { ref, computed, onMounted } from 'vue'
+import {
+  collection,
+  getDocs,
+  doc,
+  getDoc,
+  updateDoc,
+  getFirestore,
+} from 'firebase/firestore'
+
 import {
   getAuth,
   updateProfile as firebaseUpdateProfile,
-  updatePassword,
+  updatePassword
 } from 'firebase/auth'
-import {
-  getFirestore,
-  collection,
-  getDocs
-} from 'firebase/firestore'
 
+import { ref, computed, onMounted } from 'vue'
 const auth = getAuth()
 const db = getFirestore()
 
-const user = auth.currentUser
-
-const loading = ref(false)
+const user = ref(null)
 const userEmail = ref('')
 const displayName = ref('')
-const newPassword = ref('')
+const description = ref('')
 const userPhotoURL = ref('')
+const newPassword = ref('')
 const showForm = ref(false)
+const activeTab = ref('watchlist')
+const loading = ref(false)
 
 const watchlist = ref([])
+const followers = ref([])
+const following = ref([])
 
-// Load profile info
-onMounted(async () => {
-  if (user) {
-    userEmail.value = user.email
-    displayName.value = user.displayName || ''
-    userPhotoURL.value = user.photoURL || ''
-
-    // Fetch watchlist
-    const snapshot = await getDocs(collection(db, 'users', user.uid, 'watchlist'))
-    watchlist.value = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }))
-  }
-})
-
-// Password validation
 const passwordError = computed(() => {
   if (!newPassword.value) return ''
   if (newPassword.value.length < 8) return 'Password must be at least 8 characters.'
@@ -120,30 +166,104 @@ const passwordError = computed(() => {
   return ''
 })
 
-// Update profile function
+const fetchFollowing = async () => {
+  const followingSnap = await getDocs(collection(db, 'users', user.value.uid, 'following'))
+  const followedIds = followingSnap.docs.map(doc => doc.id)
+
+  const usersList = []
+
+  for (const id of followedIds) {
+    const docSnap = await getDoc(doc(db, 'users', id))
+    if (docSnap.exists()) {
+      const data = docSnap.data()
+      // Only push if the user has a displayName or isn’t hidden
+      if (!data.hidden && data.displayName) {
+        usersList.push({ uid: id, ...data })
+      }
+    }
+  }
+
+  following.value = usersList
+}
+
+const fetchFollowers = async () => {
+  if (!user.value) return
+
+  const allUsersSnap = await getDocs(collection(db, 'users'))
+  const followersList = []
+
+  for (const docSnap of allUsersSnap.docs) {
+    const otherUid = docSnap.id
+    if (otherUid === user.value.uid) continue
+
+    const followDocRef = doc(db, 'users', otherUid, 'following', user.value.uid)
+    const followDocSnap = await getDoc(followDocRef)
+
+    if (followDocSnap.exists()) {
+      const otherUserData = docSnap.data()
+      if (otherUserData.displayName && !otherUserData.hidden) {
+        followersList.push({ uid: otherUid, ...otherUserData })
+      }
+    }
+  }
+
+  followers.value = followersList
+}
+
 const handleUpdateProfile = async () => {
   if (passwordError.value) return
 
   loading.value = true
   try {
-    if (user) {
-      await firebaseUpdateProfile(user, {
-        displayName: displayName.value
-      })
+    const authUser = auth.currentUser
+    if (!authUser) throw new Error('No authenticated user')
 
-      if (newPassword.value) {
-        await updatePassword(user, newPassword.value)
-      }
+    // Update the Firebase Auth profile
+    await firebaseUpdateProfile(authUser, {
+      displayName: displayName.value
+    })
 
-      alert('Profile updated successfully!')
-      showForm.value = false
+    if (newPassword.value) {
+      await updatePassword(authUser, newPassword.value)
     }
+
+    // Update your Firestore user document
+    const userDocRef = doc(db, 'users', authUser.uid)
+    await updateDoc(userDocRef, {
+      displayName: displayName.value,
+      description: description.value
+    })
+
+    alert('Profile updated successfully!')
+    showForm.value = false
+
   } catch (error) {
     alert(error.message)
   } finally {
     loading.value = false
   }
 }
+
+onMounted(async () => {
+  const authUser = auth.currentUser
+  if (!authUser) return
+
+  user.value = authUser
+  userEmail.value = authUser.email
+  displayName.value = authUser.displayName || ''
+  userPhotoURL.value = authUser.photoURL || ''
+
+  const userDoc = await getDoc(doc(db, 'users', user.value.uid))
+  if (userDoc.exists()) {
+    description.value = userDoc.data().description || ''
+  }
+
+  const snapshot = await getDocs(collection(db, 'users', user.value.uid, 'watchlist'))
+  watchlist.value = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }))
+
+  await fetchFollowing()
+  await fetchFollowers()
+})
 </script>
 
 <style scoped>
diff --git a/movie-group-8/src/views/Register.vue b/movie-group-8/src/views/Register.vue
index 2880887..1f4d102 100644
--- a/movie-group-8/src/views/Register.vue
+++ b/movie-group-8/src/views/Register.vue
@@ -62,8 +62,18 @@
 
 <script setup>
 import { ref, computed } from 'vue';
-import { getAuth, createUserWithEmailAndPassword, signInWithPopup, GoogleAuthProvider } from 'firebase/auth';
 import { useRouter } from 'vue-router';
+import defaultAvatar from '@/assets/default_avatar.png'
+
+import { 
+  getAuth,
+  createUserWithEmailAndPassword,
+ } from 'firebase/auth';
+import {
+  getFirestore,
+  doc,
+  setDoc
+} from 'firebase/firestore';
 
 const email = ref('');
 const password = ref('');
@@ -93,9 +103,26 @@ const register = async () => {
 if (passwordError.value || confirmPasswordError.value) return;
 loading.value = true;
 try {
-  const auth = getAuth();
-  await createUserWithEmailAndPassword(auth, email.value, password.value);
-  router.push('/films');
+  const auth = getAuth()
+  const db = getFirestore()
+  const userCredential = await createUserWithEmailAndPassword(auth, email.value, password.value)
+  const user = userCredential.user
+
+  // Set default profile info
+  await updateProfile(user, {
+    displayName: 'New User',
+    photoURL: defaultAvatar
+  })
+
+  // Create Firestore document for this user
+  await setDoc(doc(db, 'users', user.uid), {
+    displayName: 'New User',
+    photoURL: defaultAvatar,
+    description: '',
+    hidden: false
+  })
+
+  router.push('/films')
 } catch (error) {
   alert(error.message);
 } finally {
-- 
GitLab


From 5a1bee3ec3f724d0878036279b68c4d23b74737d Mon Sep 17 00:00:00 2001
From: Nunu Miah <nm01312@surrey.ac.uk>
Date: Thu, 22 May 2025 22:55:38 +0100
Subject: [PATCH 3/3] Added remove from watchlist button to watchlist view,
 switched the film details page to have a new toggle button from the
 watchlistbutton component that checks to see if its already in the database
 and some other minor changes in the navbar

---
 movie-group-8/src/components/Navbar.vue       |  3 +-
 .../src/components/TopRatedMovies.vue         | 75 ++++++++++---------
 movie-group-8/src/components/Watchlist.vue    | 18 ++++-
 .../src/components/WatchlistButton.vue        | 37 +++++++++
 movie-group-8/src/composables/useWatchlist.js | 53 ++++++++++---
 movie-group-8/src/views/FilmDetails.vue       | 23 ++++--
 movie-group-8/src/views/Login.vue             | 12 +--
 movie-group-8/src/views/Social.vue            |  3 +-
 movie-group-8/src/views/WatchlistView.vue     | 47 ++++++++----
 9 files changed, 194 insertions(+), 77 deletions(-)
 create mode 100644 movie-group-8/src/components/WatchlistButton.vue

diff --git a/movie-group-8/src/components/Navbar.vue b/movie-group-8/src/components/Navbar.vue
index 1a4d4d9..64d7e57 100644
--- a/movie-group-8/src/components/Navbar.vue
+++ b/movie-group-8/src/components/Navbar.vue
@@ -74,6 +74,7 @@ import { ref, computed, onMounted } from 'vue';
 import { useRoute, useRouter } from 'vue-router';
 import { getAuth, onAuthStateChanged, signOut } from 'firebase/auth';
 import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue';
+import defaultAvatar from '@/assets/default_avatar.png'
 
 // Firebase Authentication instance
 const auth = getAuth(); 
@@ -110,7 +111,7 @@ onMounted(() => {
     if(user && user.photoURL) {
       userPhotoURL.value = user.photoURL;
     } else {
-      userPhotoURL.value = 'https://static.vecteezy.com/system/resources/previews/009/292/244/non_2x/default-avatar-icon-of-social-media-user-vector.jpg';
+      userPhotoURL.value = defaultAvatar;
     }
   });
 });
diff --git a/movie-group-8/src/components/TopRatedMovies.vue b/movie-group-8/src/components/TopRatedMovies.vue
index 5df1ea2..090e315 100644
--- a/movie-group-8/src/components/TopRatedMovies.vue
+++ b/movie-group-8/src/components/TopRatedMovies.vue
@@ -1,6 +1,5 @@
 <script setup>
 import { ref, onMounted, watch } from 'vue'
-import { addToWatchlist } from '@/composables/useWatchlist.js'
 
 const year = ref(2000)
 const genre = ref('')
@@ -28,41 +27,45 @@ watch([year, genre], async () => {
 </script>
 
 <template>
-    <div class="nyt-header">
-      <h1>The Movies We've Loved Since 2000</h1>
-      <p>
-        Explore top-rated films using the filters below — by genre and year — and rediscover hidden gems.
-      </p>
-    </div>
-  
-    <div class="filters">
-      <select v-model="genre">
-        <option value="">Pick a genre ...</option>
-        <option v-for="g in genres" :key="g.id" :value="g.id">{{ g.name }}</option>
-      </select>
-  
-      <select v-model="year">
-        <option v-for="y in Array.from({length: 25}, (_, i) => 2000 + i)" :key="y" :value="y">
-          {{ y }}
-        </option>
-      </select>
-    </div>
-  
-    <h2 class="section-title">Our favorite movies from {{ year }}</h2>
-  
-    <div class="movie-grid">
-      <div v-for="movie in movies" :key="movie.id" class="movie-card">
-        <img
-          v-if="movie.poster_path"
-          :src="'https://image.tmdb.org/t/p/w342' + movie.poster_path"
-          alt="poster"
-        />
-        <p class="title">{{ movie.title }}</p>
-        <p class="rating">⭐ {{ movie.vote_average }}</p>
-        <button @click="addToWatchlist(movie)">Add to Watchlist</button>
-      </div>
-    </div>
-  </template>
+  <div class="nyt-header">
+    <h1>The Movies We've Loved Since 2000</h1>
+    <p>
+      Explore top-rated films using the filters below — by genre and year — and rediscover hidden gems.
+    </p>
+  </div>
+
+  <div class="filters">
+    <select v-model="genre">
+      <option value="">Pick a genre ...</option>
+      <option v-for="g in genres" :key="g.id" :value="g.id">{{ g.name }}</option>
+    </select>
+
+    <select v-model="year">
+      <option v-for="y in Array.from({length: 25}, (_, i) => 2000 + i)" :key="y" :value="y">
+        {{ y }}
+      </option>
+    </select>
+  </div>
+
+  <h2 class="section-title">Our favorite movies from {{ year }}</h2>
+
+  <div class="movie-grid">
+    <router-link
+      v-for="movie in movies"
+      :key="movie.id"
+      :to="`/films/${movie.id}`"
+      class="movie-card block hover:opacity-90 transition"
+    >
+      <img
+        v-if="movie.poster_path"
+        :src="'https://image.tmdb.org/t/p/w342' + movie.poster_path"
+        alt="poster"
+      />
+      <p class="title">{{ movie.title }}</p>
+      <p class="rating">⭐ {{ movie.vote_average }}</p>
+    </router-link>
+  </div>
+</template>
   
 <style scoped>
 .nyt-header {
diff --git a/movie-group-8/src/components/Watchlist.vue b/movie-group-8/src/components/Watchlist.vue
index 968bb92..7240822 100644
--- a/movie-group-8/src/components/Watchlist.vue
+++ b/movie-group-8/src/components/Watchlist.vue
@@ -20,6 +20,12 @@
             <p class="title">{{ movie.title }}</p>
             <p class="rating">⭐ {{ movie.vote_average }}</p>
             <p class="status">📌 {{ movie.status }}</p>
+            <button
+                @click="removeFromWatchlist(movie)"
+                class="mt-2 px-3 py-1 bg-red-600 text-white rounded hover:bg-red-700 transition"
+                >
+                Remove
+            </button>
             </div>
         </div>
     </div>
@@ -27,7 +33,7 @@
   
 <script setup>
     import { ref, computed, onMounted } from 'vue'
-    import { getFirestore, collection, getDocs } from 'firebase/firestore'
+    import { getFirestore, collection, getDocs, doc, deleteDoc } from 'firebase/firestore'
     import { getAuth } from 'firebase/auth'
   
     const db = getFirestore()
@@ -43,6 +49,16 @@
         const snapshot = await getDocs(collection(db, 'users', user.uid, 'watchlist'))
         watchlist.value = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }))
     }
+
+    const removeFromWatchlist = async (movie) => {
+        const user = auth.currentUser
+        const movieRef = doc(db, 'users', user.uid, 'watchlist', String(movie.id))
+        await deleteDoc(movieRef)
+
+        // remove locally
+        watchlist.value = watchlist.value.filter(m => m.id !== movie.id)
+        alert(`Removed "${movie.title}" from your watchlist.`)
+    }
   
     const filteredWatchlist = computed(() => {
         if (!filter.value) return watchlist.value
diff --git a/movie-group-8/src/components/WatchlistButton.vue b/movie-group-8/src/components/WatchlistButton.vue
new file mode 100644
index 0000000..9145823
--- /dev/null
+++ b/movie-group-8/src/components/WatchlistButton.vue
@@ -0,0 +1,37 @@
+<template>
+  <button
+    type="button"
+    @click="toggleWatchlist"
+    class="mt-2 px-3 py-1 rounded text-white text-sm transition"
+    :class="isInWatchlist
+      ? 'bg-red-600 hover:bg-red-700'
+      : 'bg-green-600 hover:bg-green-700'"
+  >
+    {{ isInWatchlist ? 'Remove from Watchlist' : 'Add to Watchlist' }}
+  </button>
+</template>
+
+<script setup>
+import { ref, watch } from 'vue'
+import { useWatchlist } from '@/composables/useWatchlist.js'
+
+const props = defineProps({
+  movie: {
+    type: Object,
+    required: true
+  }
+})
+
+// We need a ref for the ID and a ref for the data
+const movieId = ref(props.movie.id)
+const movieData = ref(props.movie)
+
+// Pull in the composable
+const { isInWatchlist, toggleWatchlist } = useWatchlist(movieId, movieData)
+
+// If parent updates the prop, keep our ref in sync
+watch(() => props.movie, m => {
+  movieId.value = m.id
+  movieData.value = m
+})
+</script>
\ No newline at end of file
diff --git a/movie-group-8/src/composables/useWatchlist.js b/movie-group-8/src/composables/useWatchlist.js
index 7de0359..7dc09f0 100644
--- a/movie-group-8/src/composables/useWatchlist.js
+++ b/movie-group-8/src/composables/useWatchlist.js
@@ -1,18 +1,47 @@
-import { getFirestore, doc, setDoc } from 'firebase/firestore'
+import { ref, watchEffect } from 'vue'
 import { getAuth } from 'firebase/auth'
+import { getFirestore, doc, getDoc, setDoc, deleteDoc } from 'firebase/firestore'
 
-export const addToWatchlist = async (movie) => {
-  const user = getAuth().currentUser
-  if (!user) return alert('You need to log in.')
-
+export function useWatchlist(movieId, movieData) {
+  const auth = getAuth()
   const db = getFirestore()
-  const movieRef = doc(db, 'users', user.uid, 'watchlist', String(movie.id))
-  await setDoc(movieRef, {
-    title: movie.title,
-    poster_path: movie.poster_path,
-    vote_average: movie.vote_average,
-    status: 'planned'
+  const isInWatchlist = ref(false)
+
+  // Check on load & whenever movieId or user changes
+  watchEffect(async (onInvalidate) => {
+    const user = auth.currentUser
+    if (!user.value ?? user) {
+      isInWatchlist.value = false
+      return
+    }
+    const ref = doc(db, 'users', user.uid, 'watchlist', String(movieId.value ?? movieId))
+    const snap = await getDoc(ref)
+    isInWatchlist.value = snap.exists()
   })
 
-  alert('Movie added to watchlist!')
+  // Toggle function
+  const toggleWatchlist = async () => {
+    const user = auth.currentUser
+    if (!user) {
+      return alert('You need to log in.')
+    }
+    const ref = doc(db, 'users', user.uid, 'watchlist', String(movieId.value ?? movieId))
+
+    if (isInWatchlist.value) {
+      await deleteDoc(ref)
+      isInWatchlist.value = false
+      alert('Removed from watchlist')
+    } else {
+      await setDoc(ref, {
+        title: movieData.value.title,
+        poster_path: movieData.value.poster_path,
+        vote_average: movieData.value.vote_average,
+        status: 'planned'
+      })
+      isInWatchlist.value = true
+      alert('Added to watchlist')
+    }
+  }
+
+  return { isInWatchlist, toggleWatchlist }
 }
\ No newline at end of file
diff --git a/movie-group-8/src/views/FilmDetails.vue b/movie-group-8/src/views/FilmDetails.vue
index 8194f5c..fa1a9d8 100644
--- a/movie-group-8/src/views/FilmDetails.vue
+++ b/movie-group-8/src/views/FilmDetails.vue
@@ -30,12 +30,7 @@
           ></iframe>
         </div>
 
-        <button
-          @click="addToWatchlist(movie)"
-          class="mt-4 px-4 py-2 bg-green-600 rounded text-white hover:bg-green-700"
-        >
-          Add to Watchlist
-        </button>
+        <WatchlistButton :movie="movie" class="mt-4" />
 
         <RouterLink
           :to="{ name: 'ReviewFilm', params: { id: movie.id } }"
@@ -51,13 +46,18 @@
 <script setup>
 import { ref, onMounted } from 'vue'
 import { useRoute } from 'vue-router'
-import { addToWatchlist } from '@/composables/useWatchlist.js'
+import { useWatchlist } from '@/composables/useWatchlist.js'
+import WatchlistButton from '@/components/WatchlistButton.vue'
+import { getAuth } from 'firebase/auth'
+import { getFirestore, doc, getDoc } from 'firebase/firestore'
 
 const route = useRoute()
 const movie = ref(null)
 const trailerUrl = ref('')
 const loading = ref(true)
 const error = ref('')
+const movieId = ref(route.params.id)
+const { isInWatchlist } = useWatchlist(movieId, movie)
 
 function formatDate(dateString) {
   if (!dateString) return 'Unknown'
@@ -100,6 +100,15 @@ onMounted(async () => {
   const id = route.params.id
   await fetchMovieDetails(id)
   await fetchMovieVideos(id)
+
+  const user = getAuth().currentUser
+  if (user) {
+    const db = getFirestore()
+    const watchRef = doc(db, 'users', user.uid, 'watchlist', String(id))
+    const snap = await getDoc(watchRef)
+    isInWatchlist.value = snap.exists()
+  }
+
   loading.value = false
 })
 </script>
diff --git a/movie-group-8/src/views/Login.vue b/movie-group-8/src/views/Login.vue
index 909e2ed..0b539b1 100644
--- a/movie-group-8/src/views/Login.vue
+++ b/movie-group-8/src/views/Login.vue
@@ -88,17 +88,19 @@ const loading = ref(false);
 const db = getFirestore();
 
 const createUserIfNotExists = async (user) => {
-  const userRef = doc(db, 'users', user.uid);
-  const userSnap = await getDoc(userRef);
+  const userRef = doc(db, 'users', user.uid)
+  const userSnap = await getDoc(userRef)
 
   if (!userSnap.exists()) {
+    const photoURLToSave = user.photoURL || defaultAvatar
+
     await setDoc(userRef, {
       uid: user.uid,
       displayName: user.displayName || 'Anonymous',
-      photoURL: defaultAvatar
-    });
+      photoURL: photoURLToSave
+    })
   }
-};
+}
 
 const login = async () => {
   try {
diff --git a/movie-group-8/src/views/Social.vue b/movie-group-8/src/views/Social.vue
index 34bbed7..ed3b9b1 100644
--- a/movie-group-8/src/views/Social.vue
+++ b/movie-group-8/src/views/Social.vue
@@ -19,7 +19,7 @@
       >
         <router-link :to="`/user/${user.uid}`" class="flex items-center gap-4">
           <img
-            :src="user.photoURL || defaultAvatar"
+            :src="user.photoURL"
             class="w-12 h-12 rounded-full object-cover"
             alt="Avatar"
           />
@@ -58,7 +58,6 @@ const currentUser = auth.currentUser
 const searchTerm = ref('')
 const users = ref([])
 const following = ref([])
-const defaultAvatar = 'https://via.placeholder.com/150'
 
 onMounted(async () => {
   await fetchUsers()
diff --git a/movie-group-8/src/views/WatchlistView.vue b/movie-group-8/src/views/WatchlistView.vue
index 4ce8909..071b02e 100644
--- a/movie-group-8/src/views/WatchlistView.vue
+++ b/movie-group-8/src/views/WatchlistView.vue
@@ -10,12 +10,18 @@
           No movies planned yet.
         </div>
         <div class="grid gap-4">
-          <MovieCard
-            v-for="movie in plannedMovies"
-            :key="movie.id"
-            :movie="movie"
-            @status-changed="updateMovieStatus"
-          />
+          <div v-for="movie in plannedMovies" :key="movie.id" class="relative bg-white dark:bg-neutral-800 p-4 rounded">
+            <MovieCard
+              :movie="movie"
+              @status-changed="updateMovieStatus"
+            />
+            <button
+              @click="removeFromWatchlist(movie.id)"
+              class="absolute top-2 right-2 px-2 py-1 bg-red-600 text-white text-xs rounded hover:bg-red-700 transition"
+            >
+              Remove
+            </button>
+          </div>
         </div>
       </div>
 
@@ -26,12 +32,18 @@
           No watched movies yet.
         </div>
         <div class="grid gap-4">
-          <MovieCard
-            v-for="movie in watchedMovies"
-            :key="movie.id"
-            :movie="movie"
-            @status-changed="updateMovieStatus"
-          />
+          <div v-for="movie in watchedMovies" :key="movie.id" class="relative bg-white dark:bg-neutral-800 p-4 rounded">
+            <MovieCard
+              :movie="movie"
+              @status-changed="updateMovieStatus"
+            />
+            <button
+              @click="removeFromWatchlist(movie.id)"
+              class="absolute top-2 right-2 px-2 py-1 bg-red-600 text-white text-xs rounded hover:bg-red-700 transition"
+            >
+              Remove
+            </button>
+          </div>
         </div>
       </div>
     </div>
@@ -41,7 +53,7 @@
 <script setup>
 import { ref, onMounted } from 'vue'
 import { getAuth } from 'firebase/auth'
-import { getFirestore, collection, getDocs, doc, updateDoc } from 'firebase/firestore'
+import { getFirestore, collection, getDocs, doc, updateDoc, deleteDoc } from 'firebase/firestore'
 import MovieCard from '@/components/MovieCard.vue'
 
 const auth = getAuth()
@@ -60,6 +72,15 @@ const fetchWatchlist = async () => {
   watchedMovies.value = all.filter(m => m.status === 'watched')
 }
 
+const removeFromWatchlist = async (movieId) => {
+  const user = auth.currentUser
+  if (!user) return
+
+  const movieRef = doc(db, 'users', user.uid, 'watchlist', movieId)
+  await deleteDoc(movieRef)
+  await fetchWatchlist()
+}
+
 const updateMovieStatus = async (movieId, newStatus) => {
   const user = auth.currentUser
   if (!user) return
-- 
GitLab