diff --git a/src/components/BaseComponents/CommunityHeader.vue b/src/components/BaseComponents/CommunityHeader.vue index 9d36eafc7790593410c54a64a51c3406cb1eeed7..4c1ca2e5bf326f0df9f75ed1ba0fce7bf82fcab5 100644 --- a/src/components/BaseComponents/CommunityHeader.vue +++ b/src/components/BaseComponents/CommunityHeader.vue @@ -48,7 +48,7 @@ <!-- If the user is member of the community, this hamburger menu will show --> <div v-if="member"> <svg - @click="toggle" + @click="toggleHamburgerMenu()" xmlns="http://www.w3.org/2000/svg" class="w-9 h-9 cursor-pointer" fill="none" @@ -67,6 +67,7 @@ v-if="hamburgerOpen" class="origin-top-right absolute right-0" :community-i-d="community.communityId" + :admin="admin" /> <!-- class="absolute" --> </div> @@ -77,11 +78,12 @@ <script> import CommunityHamburger from "@/components/CommunityComponents/CommunityHamburger"; import ColoredButton from "@/components/BaseComponents/ColoredButton"; +import CommunityService from "@/services/community.service"; +import CustomFooterModal from "@/components/BaseComponents/CustomFooterModal"; import { JoinOpenCommunity, GetIfUserAlreadyInCommunity, } from "@/utils/apiutil"; -import CustomFooterModal from "@/components/BaseComponents/CustomFooterModal"; export default { name: "CommunityHeader", @@ -95,27 +97,15 @@ export default { hamburgerOpen: false, dialogOpen: false, member: true, + community: {}, }; }, props: { - adminStatus: Boolean, - community: { - communityId: Number, - name: String, - description: String, - visibility: Number, - location: String, - picture: String, - }, + admin: Boolean, }, methods: { - //To open and close the hamburger menu - toggle: function () { - if (this.hamburgerOpen) { - this.hamburgerOpen = false; - } else { - this.hamburgerOpen = true; - } + toggleHamburgerMenu() { + this.hamburgerOpen = !this.hamburgerOpen; }, joinCommunity: async function (id) { const response = await JoinOpenCommunity(id); @@ -138,5 +128,10 @@ export default { beforeMount() { this.getIfUserInCommunity(); }, + async mounted() { + this.community = await CommunityService.getCommunity( + this.$route.params.communityID + ); + }, }; </script> diff --git a/src/components/BaseComponents/IconButton.vue b/src/components/BaseComponents/IconButton.vue index 6d06eca8b13b48b0dda39979e7b4d5bdc6a895d5..095db5635e33e9a5116c0724f8a77a8a8c5acb93 100644 --- a/src/components/BaseComponents/IconButton.vue +++ b/src/components/BaseComponents/IconButton.vue @@ -1,14 +1,4 @@ <template> - <!-- Icon button --> - <!-- BUTTON CSS - block w-fit text-white text-base bg-primary-medium hover:bg-primary-dark focus:ring-4 focus:outline-none focus:ring-primary-light font-medium rounded-lg text-center dark:bg-primary-medium dark:hover:bg-primary-dark dark:focus:ring-primary-dark - - DIV CSS - flex flex-row px-5 py-2.5 h-10 - - ICON CSS - h-6 w-6 - --> <button class="flex items-center px-2 py-2 font-medium tracking-wide capitalize text-white transition-colors duration-200 transform rounded-md focus:outline-none focus:ring focus:ring-opacity-80" :class="color" diff --git a/src/components/CommunityComponents/Admin/AdministrateMembers.vue b/src/components/CommunityComponents/Admin/AdministrateMembers.vue deleted file mode 100644 index 54668d98c24f40673b2b93a44eb3b50a85f32e38..0000000000000000000000000000000000000000 --- a/src/components/CommunityComponents/Admin/AdministrateMembers.vue +++ /dev/null @@ -1,43 +0,0 @@ -<template> - <ul> - <li v-for="member in memberlist" :key="member.userId"> - <UserListItemCard :admin="admin" :user="member" /> - </li> - </ul> -</template> - -<script> -import UserListItemCard from "../UserProfileComponents/UserListItemCard.vue"; -import { GetMembersOfCommunity, GetCommunity } from "@/utils/apiutil"; - -export default { - data() { - return { - memberlist: [], - community: {}, - }; - }, - components: { - UserListItemCard, - }, - props: { - admin: Boolean, - }, - methods: { - getAllMembersOfCommunity: async function () { - this.memberlist = await GetMembersOfCommunity( - this.$router.currentRoute.value.params.id - ); - }, - getCommunity: async function () { - this.community = await GetCommunity( - this.$router.currentRoute.value.params.id - ); - }, - }, - beforeMount() { - this.getAllMembersOfCommunity(); - this.getCommunity(); - }, -}; -</script> diff --git a/src/components/CommunityComponents/CommunityHamburger.vue b/src/components/CommunityComponents/CommunityHamburger.vue index e32015c656c707bb8851e9915ff4f083aacec388..f933ac305b5f0a958e099c491e746409e24dbea3 100644 --- a/src/components/CommunityComponents/CommunityHamburger.vue +++ b/src/components/CommunityComponents/CommunityHamburger.vue @@ -18,7 +18,7 @@ >Se Medlemmer </router-link> </li> - <li id="adminGroup"> + <li id="adminGroup" v-if="admin"> <router-link :to="'/group/' + communityID + '/admin'" class="block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white" @@ -27,7 +27,7 @@ </li> <li id="leaveGroup"> <div - class="cursor-pointer block py-2 px-4 text-sm text-red-600 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white" + class="cursor-pointer block py-2 px-4 text-sm text-error-medium hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white" > Forlat Gruppe </div> @@ -41,6 +41,7 @@ export default { name: "CommunityHamburger", props: { communityID: Number, + admin: Boolean, }, }; </script> diff --git a/src/components/CommunityComponents/CommunityHome.vue b/src/components/CommunityComponents/CommunityHome.vue index cf2ae250d449cbfbe5280abe1b5b34e228cf44c0..1f7dcca6aa9c88192fac1263c49fa25da1c4697e 100644 --- a/src/components/CommunityComponents/CommunityHome.vue +++ b/src/components/CommunityComponents/CommunityHome.vue @@ -1,10 +1,6 @@ <template> <section class="w-full px-5 py-4 mx-auto rounded-md"> - <CommunityHeader - :admin-status="false" - :community="community" - class="mb-5" - /> + <CommunityHeader :admin="false" class="mb-5" /> <!-- Search field --> <div class="relative" id="searchComponent"> @@ -50,7 +46,6 @@ export default { CommunityHeader, ItemCard, }, - computed: { searchedItems() { let filteredItems = []; diff --git a/src/components/CommunityComponents/MemberList.vue b/src/components/CommunityComponents/MemberList.vue index a86630f9520234f865c470238d0b53c70d1d6285..d8e3b2aa6b7a22ee8c487257f1659d7d94072593 100644 --- a/src/components/CommunityComponents/MemberList.vue +++ b/src/components/CommunityComponents/MemberList.vue @@ -1,43 +1,30 @@ <template> <ul> - <li v-for="member in memberlist" :key="member.userId"> - <user-list-item-card :admin="admin" :user="member" /> + <li v-for="member in members" :key="member.userId"> + <UserListItemCard :buttons="buttons" :user="member" /> </li> </ul> </template> <script> import UserListItemCard from "../UserProfileComponents/UserListItemCard.vue"; -import { GetMembersOfCommunity, GetCommunity } from "@/utils/apiutil"; +import { GetMembersOfCommunity } from "@/utils/apiutil"; export default { - data() { - return { - memberlist: [], - community: {}, - }; - }, + name: "MemberList", components: { UserListItemCard, }, props: { - admin: Boolean, + buttons: Array, }, - methods: { - getAllMembersOfCommunity: async function () { - this.memberlist = await GetMembersOfCommunity( - this.$router.currentRoute.value.params.id - ); - }, - getCommunity: async function () { - this.community = await GetCommunity( - this.$router.currentRoute.value.params.id - ); - }, + data() { + return { + members: [], + }; }, - beforeMount() { - this.getAllMembersOfCommunity(); - this.getCommunity(); + async created() { + this.members = await GetMembersOfCommunity(this.$route.params.communityID); }, }; </script> diff --git a/src/components/UserProfileComponents/UserListItemCard.vue b/src/components/UserProfileComponents/UserListItemCard.vue index 90180d2df55f207bf11a4ebe1fab595da63bf1f4..31fdf25d7738b595cc5c49c53aa8699890e79ecc 100644 --- a/src/components/UserProfileComponents/UserListItemCard.vue +++ b/src/components/UserProfileComponents/UserListItemCard.vue @@ -2,67 +2,112 @@ <div class="bg-white shadow dark:bg-gray-800 select-none cursor-pointer hover:bg-gray-50 flex items-center p-4" > + <!-- User image --> <div class="h-10 w-10 flex flex-col justify-center items-center mr-4"> <router-link :to="'/profile/' + user.userId"> - <img alt="profil" src="../../assets/defaultUserProfileImage.jpg" /> + <img alt="Profilbilde" src="../../assets/defaultUserProfileImage.jpg" /> </router-link> </div> + + <!-- User name --> <div class="flex-1 pl-1"> <div class="font-medium dark:text-white"> {{ user.firstName }} {{ user.lastName }} </div> </div> + + <!-- User rating --> <div class="hidden md:block flex-auto"> - <rating-component :rating="rating" :ratingType="'Gjennomsnitts rating'" /> + <RatingComponent :rating="rating" :ratingType="'Gjennomsnitts rating'" /> </div> - <div class="flex flex-row justify-center"> - <button - v-if="!admin" - class="px-4 py-2 font-medium tracking-wide text-white capitalize transition-colors duration-200 transform bg-blue-600 rounded-md hover:bg-blue-500 focus:outline-none focus:ring focus:ring-blue-300 focus:ring-opacity-80" - > - Åpne chat - </button> - <button - v-if="admin" - class="px-4 py-2 font-medium tracking-wide text-white capitalize transition-colors duration-200 transform bg-blue-600 rounded-md hover:bg-blue-500 focus:outline-none focus:ring focus:ring-blue-300 focus:ring-opacity-80" + + <!-- Buttons --> + <div class="flex flex-row gap-4"> + <IconButton + v-if="buttons.includes('chat')" + @click="openChatWithUser()" + :text="'Chat'" + :buttonColor="'blue'" > - Fjern bruker - </button> + <ChatIcon + /></IconButton> + + <IconButton + v-if="buttons.includes('kick')" + @click="kickUserFromCommunity()" + :buttonColor="'red'" + :text="'Spark'" + ><BanIcon + /></IconButton> + + <IconButton + v-if="buttons.includes('accept')" + @click="acceptMemberRequest()" + :buttonColor="'green'" + :text="'Godta'" + ><CheckCircleIcon + /></IconButton> + + <IconButton + v-if="buttons.includes('reject')" + @click="rejectMemberRequest()" + :buttonColor="'red'" + :text="'Avslå'" + ><XCircleIcon + /></IconButton> </div> </div> </template> <script> -import { getAverageRating } from "@/utils/apiutil"; -import RatingComponent from "./Rating.vue"; +import RatingComponent from "@/components/UserProfileComponents/Rating.vue"; +import IconButton from "@/components/BaseComponents/IconButton.vue"; +import UserService from "@/services/user.service"; +import { + ChatIcon, + CheckCircleIcon, + BanIcon, + XCircleIcon, +} from "@heroicons/vue/outline"; export default { name: "UserListItem", data() { return { - rating: this.getRating(), + rating: -1.0, }; }, components: { RatingComponent, + IconButton, + ChatIcon, + CheckCircleIcon, + BanIcon, + XCircleIcon, }, props: { user: Object, - admin: Boolean, + buttons: Array, }, methods: { getProfilePicture() { if (this.user.picture != "") { return this.user.picture; } - return "../assets/defaultUserProfileImage.jpg"; + return "@/assets/defaultUserProfileImage.jpg"; }, - async getRating() { - this.rating = await getAverageRating(this.user.userId); + openChatWithUser() { + this.$router.push({ + name: "messages", + params: { userId: this.user.userId }, + }); }, + kickUserFromCommunity() {}, + acceptMemberRequest() {}, + rejectMemberRequest() {}, }, - beforeMount() { - this.getRating(); + async created() { + this.rating = await UserService.getUserRatingAverage(this.user.userId); }, }; </script> diff --git a/src/router/index.js b/src/router/index.js index 85b7e8fd153ea4eb91b038a43a0a431f2dfc0d03..270883ea8f2db85c221b6f719c90f427ac1fc21f 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -70,7 +70,7 @@ const routes = [ component: () => import("../views/CommunityViews/NewCommunityView.vue"), }, { - path: "/group/:id/memberlist", + path: "/group/:communityID/memberlist", name: "memberlist", component: () => import("../views/CommunityViews/MemberListView.vue"), beforeEnter: guardRoute, @@ -104,9 +104,10 @@ const routes = [ component: () => import("../views/TestView.vue"), }, { - path: "/group/:id/admin", - name: "CommunityAdmin", - component: () => import("@/views/CommunityViews/CommunityAdminView.vue"), + path: "/group/:communityID/admin", + name: "CommunityAdminView", + component: () => import("@/views/CommunityViews/AdminView.vue"), + beforeEnter: guardRoute, }, ]; diff --git a/src/utils/apiutil.js b/src/utils/apiutil.js index cb8d309196adad2d43b6edc56e6f5b8348f40c4d..d7703d811a1afc2c755a65b6ee820399b746bb3a 100644 --- a/src/utils/apiutil.js +++ b/src/utils/apiutil.js @@ -149,7 +149,7 @@ export function getVisibleGroups() { } export async function GetCommunity(communityID) { - return axios + return await axios .get(API_URL + "community/" + communityID, { headers: tokenHeader(), }) diff --git a/src/views/ChatViews/ChatView.vue b/src/views/ChatViews/ChatView.vue index a8c5eef7738240b1779ff766608661cd8bdbb953..1b7cfad3b7730e1991953a8f5340ff45669f568b 100644 --- a/src/views/ChatViews/ChatView.vue +++ b/src/views/ChatViews/ChatView.vue @@ -1,32 +1,40 @@ <template> - <div class="min-h-full"> + <div class="flex flex-col h-full overflow-hidden border-2"> + <div class="flex flex-row h-full border-2 bg-gray-50"> + <div class="basis-1/3"> + <h1 class="text-center text-l">Mine samtaler</h1> + <ul v-if="conversations" class="border-2"> + <li + v-for="conversation in conversations" + :key="conversation.recipient.userId" + > + <ChatProfile :conversation="conversation" @recipient="selectUser" /> + </li> + </ul> + </div> + <div class="basis-2/3"> + <CurrentChat v-if="selected" :recipient="selected" /> + </div> + </div> + </div> + <!-- <div class="min-h-full"> <div class="border rounded grid grid-cols-3 w-full"> <div class="border-r border-gray-300 col-span-1"> <ul class="hidden sm:block overflow-auto h-full"> <h2 class="my-2 mb-2 ml-2 text-lg text-gray-600">Chats</h2> - <li> - <ChatProfile - v-for="(conversation, i) in conversations" - :conversation="conversation" - :key="i" - @recipient="selectUser" - ></ChatProfile> + <li v-if="conversations"> </li> </ul> </div> - <CurrentChat - v-if="selected" - :recipient="selected" - :key="key" - ></CurrentChat> </div> - </div> + </div> --> </template> <script> import ChatProfile from "@/components/ChatComponents/ChatProfile.vue"; import CurrentChat from "@/components/ChatComponents/CurrentChat.vue"; import { parseCurrentUser } from "@/utils/token-utils"; +import ChatService from "@/services/chat.service"; export default { components: { @@ -40,14 +48,14 @@ export default { }; }, computed: { - userID() { - return parseCurrentUser().accountId; - }, key() { return this.selected.userId || "ERROR"; }, }, methods: { + userID() { + return parseCurrentUser().accountId; + }, selectUser(value) { const userid = value; this.conversations.find((conversation) => { @@ -60,17 +68,10 @@ export default { }, }, async created() { - const token = this.$store.state.user.token; - // Get all conversations from api with /chats/users - const response = await fetch(`${process.env.VUE_APP_BASEURL}chats/users`, { - method: "GET", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${token}`, - }, - }); // add error handling - const res = await response.json(); - this.conversations = res; + this.conversations = await ChatService.getConversations(this.userID()); + if (this.$route.params.userId !== null) { + this.selectUser(this.$route.params.userId); + } }, }; </script> diff --git a/src/views/CommunityViews/CommunityAdminView.vue b/src/views/CommunityViews/CommunityAdminView.vue deleted file mode 100644 index c7bbc03ff1dafdf0e275f4774fdd7443a6af478c..0000000000000000000000000000000000000000 --- a/src/views/CommunityViews/CommunityAdminView.vue +++ /dev/null @@ -1,60 +0,0 @@ -<template> - <div class="flex border-b border-gray-200 dark:border-gray-700"> - <button - v-for="(tab, index) in tabs" - :key="tab" - @click="changeTab(tab, index)" - class="h-10 px-4 py-2 -mb-px text-sm text-center bg-transparent border-b-2 sm:text-base whitespace-nowrap focus:outline-none" - :class="[activeTab === index ? activeClasses : inactiveClasses]" - > - {{ tabNames[index] }} - </button> - </div> - <MemberList v-if="loadedComponent === 'MemberList'" /> -</template> - -<script> -import MemberList from "@/components/CommunityComponents/MemberList.vue"; - -export default { - name: "CommunityAdminView", - components: { - MemberList, - }, - data() { - return { - tabs: ["MemberList", "Hey"], - tabNames: ["Medlemsliste", "Medlemsforespørsler"], - activeTab: 0, - loadedComponent: "MemberList", - }; - }, - methods: { - changeTab(tab, index) { - this.loadedComponent = tab; - this.activeTab = index; - }, - }, - computed: { - activeClasses() { - return { - "text-blue-600": true, - "border-blue-500": true, - "dark:border-blue-400": true, - "dark:text-blue-300": true, - }; - }, - inactiveClasses() { - return { - "text-gray-700": true, - "border-transparent": true, - "dark:text-white": true, - "cursor-base": true, - "hover:border-gray-400": true, - }; - }, - }, -}; -</script> - -<style></style> diff --git a/src/views/CommunityViews/CommunityView.vue b/src/views/CommunityViews/CommunityView.vue index 9fd39f5f305a7592f633795254899fa3cf3883a8..e207d85c264c56de681be55e4f5f676b1af31ffa 100644 --- a/src/views/CommunityViews/CommunityView.vue +++ b/src/views/CommunityViews/CommunityView.vue @@ -40,6 +40,7 @@ export default { this.myCommunities = await getMyGroups(); + //FIX TOMROWKRO // Remove all of the user's communities from the public communities arrays this.publicCommunities = this.publicCommunities.filter( (val) => !this.myCommunities.includes(val) diff --git a/src/views/CommunityViews/MemberListView.vue b/src/views/CommunityViews/MemberListView.vue index 660cff6f880cc3abeedde2a324a9bd5c9674d7e4..26abf8977661a751ec1efbe4a6921ed8b64517c1 100644 --- a/src/views/CommunityViews/MemberListView.vue +++ b/src/views/CommunityViews/MemberListView.vue @@ -1,10 +1,6 @@ <template> - <CommunityHeader - :admin-status="false" - :community="community" - class="mb-5 mt-5" - /> - <MemberList /> + <CommunityHeader :admin="false" class="mb-5 mt-5" /> + <MemberList :buttons="['chat']" /> </template> <script>