|
@@ -5,172 +5,268 @@ import Sidebar from '@/components/Sidebar.vue'
|
|
|
import { config } from '@/main.js'
|
|
|
import axios from 'axios'
|
|
|
import VideoSearchResult from '@/components/VideoSearchResult.vue'
|
|
|
+import ProfileSearchResult from '@/components/ProfileSearchResult.vue'
|
|
|
|
|
|
export default defineComponent({
|
|
|
- name: 'SearchView',
|
|
|
- components: { VideoSearchResult, Sidebar, SearchIcon },
|
|
|
- methods: {
|
|
|
- async search(searchQuery = null) {
|
|
|
- let searchBar;
|
|
|
- if(searchQuery == null) { searchBar = document.getElementById('search-bar') }
|
|
|
- else { searchBar = { value: searchQuery } }
|
|
|
- const searchStatus = document.getElementById('search-status');
|
|
|
-
|
|
|
- console.log(searchBar.value);
|
|
|
- if (searchBar.value.trim() === '') return (searchStatus.innerText = `no`)
|
|
|
- searchStatus.innerText = 'searching!!'
|
|
|
- const response = await axios.post(`${config.serverURL}/video/search`, {
|
|
|
- query: searchBar.value,
|
|
|
- })
|
|
|
-
|
|
|
- if (response.data.error)
|
|
|
- return (searchStatus.innerText = `search error: ${response.data.error}`)
|
|
|
- if (response.data.length === 0) return (searchStatus.innerText = 'no results :(')
|
|
|
-
|
|
|
- this.searchResults = response.data
|
|
|
- searchStatus.innerText = '';
|
|
|
- },
|
|
|
- },
|
|
|
- data() {
|
|
|
- return {
|
|
|
- searchResults: null,
|
|
|
- }
|
|
|
- },
|
|
|
- mounted () {
|
|
|
- const searchParams = new URLSearchParams(window.location.search);
|
|
|
- if(searchParams.get('searchQuery')) this.search(searchParams.get('searchQuery'));
|
|
|
- }
|
|
|
+ name: 'SearchView',
|
|
|
+ components: { ProfileSearchResult, VideoSearchResult, Sidebar, SearchIcon },
|
|
|
+ methods: {
|
|
|
+ async search(searchQuery = null) {
|
|
|
+ let searchBar
|
|
|
+ if (searchQuery == null) {
|
|
|
+ searchBar = document.getElementById('search-bar')
|
|
|
+ } else {
|
|
|
+ searchBar = { value: searchQuery }
|
|
|
+ }
|
|
|
+ const searchStatus = document.getElementById('search-status')
|
|
|
+
|
|
|
+ console.log(searchBar.value)
|
|
|
+ if (searchBar.value.trim() === '') return (searchStatus.innerText = `no`)
|
|
|
+ searchStatus.innerText = 'searching!!'
|
|
|
+ let url = `${config.serverURL}/video/search`
|
|
|
+ if (this.selectedTab === 'accounts') url = `${config.serverURL}/account/search`
|
|
|
+
|
|
|
+ const response = await axios.post(
|
|
|
+ url,
|
|
|
+ { query: searchBar.value },
|
|
|
+ { withCredentials: true },
|
|
|
+ )
|
|
|
+
|
|
|
+ if (response.data.error)
|
|
|
+ return (searchStatus.innerText = `search error: ${response.data.error}`)
|
|
|
+ if (response.data.length === 0) return (searchStatus.innerText = 'no results :(')
|
|
|
+
|
|
|
+ this.searchResults = response.data
|
|
|
+ searchStatus.innerText = ''
|
|
|
+ },
|
|
|
+
|
|
|
+ selectTab(tab) {
|
|
|
+ this.selectedTab = tab
|
|
|
+ document.querySelector('.selected').classList.remove('selected')
|
|
|
+ document.querySelector(`#${tab}-tab`).classList.add('selected')
|
|
|
+ document.querySelectorAll('.search-results').forEach((div) => {
|
|
|
+ div.innerHTML = ''
|
|
|
+ })
|
|
|
+
|
|
|
+ const searchBar = document.getElementById('search-bar')
|
|
|
+ const searchStatus = document.getElementById('search-status')
|
|
|
+ if (searchBar.value.trim() !== '') this.search()
|
|
|
+ searchStatus.innerText = ''
|
|
|
+ },
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ searchResults: null,
|
|
|
+ selectedTab: 'videos',
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ const searchParams = new URLSearchParams(window.location.search)
|
|
|
+ if (searchParams.get('searchQuery')) this.search(searchParams.get('searchQuery'))
|
|
|
+ },
|
|
|
})
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
- <div class="main">
|
|
|
- <Sidebar />
|
|
|
- <div class="search-container">
|
|
|
- <div class="search-bar-container">
|
|
|
- <button class="search-button" @click="search()">
|
|
|
- <SearchIcon :size="50" />
|
|
|
- </button>
|
|
|
- <input type="text" placeholder="Search" class="search-bar" id="search-bar" />
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="search-status" id="search-status"></div>
|
|
|
- <div class="search-results" id="search-results" v-for="video in searchResults">
|
|
|
- <VideoSearchResult
|
|
|
- :id="video.id"
|
|
|
- :title="video.title"
|
|
|
- :author="video.author.username"
|
|
|
- :likes="video.likes"
|
|
|
- :dislikes="video.dislikes"
|
|
|
- :comments="video.comments"
|
|
|
- :shares="video.shares"
|
|
|
- />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <div class="main">
|
|
|
+ <Sidebar />
|
|
|
+ <div class="search-container">
|
|
|
+ <div class="tab-conglomerate">
|
|
|
+ <div class="tab-row">
|
|
|
+ <button class="india-tab selected" id="videos-tab" @click="selectTab('videos')">
|
|
|
+ videos
|
|
|
+ </button>
|
|
|
+ <button class="india-tab" id="accounts-tab" @click="selectTab('accounts')">
|
|
|
+ accounts
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ <div class="search-bar-container">
|
|
|
+ <button class="search-button" @click="search()">
|
|
|
+ <SearchIcon :size="50" />
|
|
|
+ </button>
|
|
|
+ <input type="text" placeholder="Search" class="search-bar" id="search-bar" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="search-status" id="search-status"></div>
|
|
|
+ <div class="search-results" id="search-results" v-if="this.selectedTab === 'videos'">
|
|
|
+ <VideoSearchResult
|
|
|
+ :id="video.id"
|
|
|
+ :title="video.title"
|
|
|
+ :author="video.author.username"
|
|
|
+ :author-id="video.author.id"
|
|
|
+ :likes="video.likes"
|
|
|
+ :dislikes="video.dislikes"
|
|
|
+ :comments="video.comments"
|
|
|
+ :shares="video.shares"
|
|
|
+ :verified="video.author.verified"
|
|
|
+ v-for="video in searchResults"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="search-results" id="search-results" v-else>
|
|
|
+ <ProfileSearchResult
|
|
|
+ :social-credit="profile.socialCredit"
|
|
|
+ :followers="profile.followers"
|
|
|
+ :following="profile.following"
|
|
|
+ :username="profile.username"
|
|
|
+ :id="profile.id"
|
|
|
+ :verified="profile.verified"
|
|
|
+ v-for="profile in searchResults"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
<style scoped>
|
|
|
.main {
|
|
|
- width: 100vw;
|
|
|
- height: 100vh;
|
|
|
- margin: 0;
|
|
|
- display: flex;
|
|
|
- flex-direction: row;
|
|
|
+ width: 100vw;
|
|
|
+ height: 100vh;
|
|
|
+ margin: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
}
|
|
|
|
|
|
.search-results {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- flex-direction: column;
|
|
|
- gap: 10px;
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+ justify-content: flex-start;
|
|
|
+ padding-left: 20px;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+
|
|
|
+ max-height: calc(100vh - 300px);
|
|
|
+ overflow-y: scroll;
|
|
|
+ overflow-x: hidden;
|
|
|
+ width: 100%;
|
|
|
+ flex-grow: 1;
|
|
|
}
|
|
|
|
|
|
.search-container {
|
|
|
- /* I have to do % instead of vw and vh for the proper sizing with the sidebar !! !! !! */
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- margin: 0;
|
|
|
-
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- gap: 10px;
|
|
|
- padding: 20px;
|
|
|
-
|
|
|
- justify-content: space-evenly;
|
|
|
- align-items: center;
|
|
|
+ /* I have to do % instead of vw and vh for the proper sizing with the sidebar !! !! !! */
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ margin: 0;
|
|
|
+
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+ padding: 20px;
|
|
|
+
|
|
|
+ justify-content: space-evenly;
|
|
|
+ align-items: center;
|
|
|
}
|
|
|
|
|
|
.search-bar-container {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- gap: 10px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ gap: 10px;
|
|
|
|
|
|
- background-color: var(--text-color);
|
|
|
- border-radius: 10px;
|
|
|
+ background-color: var(--text-color);
|
|
|
+ border-radius: 10px;
|
|
|
|
|
|
- width: calc(100% - 200px);
|
|
|
+ width: calc(100% - 200px);
|
|
|
}
|
|
|
|
|
|
.search-bar {
|
|
|
- padding: 6px;
|
|
|
- font-size: 20px;
|
|
|
- background-color: var(--text-color);
|
|
|
- border: none;
|
|
|
- color: var(--inverted-text-color);
|
|
|
- font-family: "Knewave", system-ui;
|
|
|
- width: calc(100% - 100px);
|
|
|
+ padding: 6px;
|
|
|
+ font-size: 20px;
|
|
|
+ background-color: var(--text-color);
|
|
|
+ border: none;
|
|
|
+ color: var(--inverted-text-color);
|
|
|
+ font-family: 'Knewave', system-ui;
|
|
|
+ width: calc(100% - 100px);
|
|
|
}
|
|
|
|
|
|
.search-bar:focus {
|
|
|
- outline: none;
|
|
|
+ outline: none;
|
|
|
}
|
|
|
|
|
|
.search-button {
|
|
|
- background-color: transparent;
|
|
|
- border: none;
|
|
|
+ background-color: transparent;
|
|
|
+ border: none;
|
|
|
}
|
|
|
|
|
|
.search-button:hover {
|
|
|
- cursor: pointer;
|
|
|
- animation-name: interaction;
|
|
|
- animation-duration: 1s;
|
|
|
- animation-iteration-count: infinite;
|
|
|
+ cursor: pointer;
|
|
|
+ animation-name: interaction;
|
|
|
+ animation-duration: 1s;
|
|
|
+ animation-iteration-count: infinite;
|
|
|
}
|
|
|
|
|
|
.search-status {
|
|
|
- position: absolute;
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
-
|
|
|
- font-size: 70px;
|
|
|
- font-family: "Pinyon Script", cursive;
|
|
|
- color: var(--accent-color);
|
|
|
- text-shadow: 5px 5px 5px #fbff00;
|
|
|
-
|
|
|
- animation-name: interaction;
|
|
|
- animation-duration: 0.2s;
|
|
|
- animation-iteration-count: infinite;
|
|
|
-
|
|
|
- pointer-events: none;
|
|
|
+ position: absolute;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+
|
|
|
+ font-size: 70px;
|
|
|
+ font-family: 'Pinyon Script', cursive;
|
|
|
+ color: var(--accent-color);
|
|
|
+ text-shadow: 5px 5px 5px #fbff00;
|
|
|
+
|
|
|
+ animation-name: interaction;
|
|
|
+ animation-duration: 0.2s;
|
|
|
+ animation-iteration-count: infinite;
|
|
|
+
|
|
|
+ pointer-events: none;
|
|
|
}
|
|
|
|
|
|
-@keyframes interaction {
|
|
|
- 0% {
|
|
|
- transform: scale(1);
|
|
|
- }
|
|
|
+.india-tab {
|
|
|
+ padding: 10px 10px;
|
|
|
+ background: none;
|
|
|
+ color: var(--accent-color);
|
|
|
+ font-family: 'Pinyon Script', cursive;
|
|
|
+ font-size: 30px;
|
|
|
|
|
|
- 50% {
|
|
|
- transform: scale(1.2);
|
|
|
- }
|
|
|
+ border-style: solid;
|
|
|
+ border-width: 0 20px;
|
|
|
+ border-image-source: url('/assets/indiaTab.png');
|
|
|
+ border-image-slice: 0 80 fill;
|
|
|
+ border-radius: 40px;
|
|
|
+ background-clip: padding-box;
|
|
|
+}
|
|
|
+
|
|
|
+.india-tab:hover {
|
|
|
+ cursor: pointer;
|
|
|
+ animation-name: tab-interaction;
|
|
|
+ animation-duration: 0.2s;
|
|
|
+ animation-iteration-count: infinite;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-conglomerate {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 0px;
|
|
|
+
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.tab-row {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ gap: 20px;
|
|
|
+}
|
|
|
|
|
|
- 100% {
|
|
|
- transform: scale(1);
|
|
|
- }
|
|
|
+.selected {
|
|
|
+ transform: scaleY(1.5) translateY(-20%);
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes tab-interaction {
|
|
|
+ 0% {
|
|
|
+ transform: scaleY(1) translateY(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ 50% {
|
|
|
+ transform: scaleY(1.5) translateY(-20%);
|
|
|
+ }
|
|
|
+
|
|
|
+ 100% {
|
|
|
+ transform: scaleY(1) translateY(0);
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|