Commit b8c204a9 authored by erlendoeien's avatar erlendoeien
Browse files

Add working movies search

parent b6de5b9b
{ "printWidth": 100 }
import useFilteredMovies from "./useFilteredMovies";
import useWishlistMovies from "./useWishlistMovies";
import useMovies from "./useMovies";
import useWishlist from "./useWishlist";
import useCurrentUser from "./useCurrentUser";
import useMatchedMovies from "./useMatchedMovies";
export { useFilteredMovies, useMovies, useWishlist, useCurrentUser };
export { useWishlistMovies, useMovies, useWishlist, useMatchedMovies, useCurrentUser };
import { computed, ref, Ref } from "@vue/runtime-dom";
import { IMovie } from "../types";
import _debounce from "lodash/debounce";
export default function useMatchedMovies(movies: Ref<IMovie[]>) {
const searchQuery = ref("");
const matchPredicate = ({ genre, title, year }: IMovie) =>
genre.indexOf(searchQuery.value) > -1 ||
title.indexOf(searchQuery.value) > -1 ||
year.indexOf(searchQuery.value) > -1;
const moviesMatchingSearchQuery = computed(() => {
if (searchQuery.value.length === 0) return movies.value;
return movies.value.filter(matchPredicate);
});
return { searchQuery, moviesMatchingSearchQuery };
}
import { getUsername } from "../tools/databaseTools";
import { getAuth } from "@firebase/auth";
import { ref } from "@vue/reactivity";
import { IListeners, IMovie } from "../types";
import { IListeners, IMovie, IMovieRaw } from "../types";
import { getDatabase, ref as fbRef } from "@firebase/database";
import { onMounted, onBeforeUnmount, Ref, watch } from "@vue/runtime-dom";
import { onValue } from "firebase/database";
......@@ -19,7 +19,16 @@ export default function useMovies() {
listeners.movies = onValue(
moviesRef,
(snapshot) => {
movies.value = snapshot.val();
const _movies: IMovie[] = [];
snapshot.forEach((movieSnap) => {
const movie = movieSnap.val() as IMovieRaw;
_movies.push({
...movie,
title: movie.title.toString(),
year: movie.year.toString(),
});
});
movies.value = _movies;
},
{ onlyOnce: true }
);
......
import {
getDatabase,
onValue,
push,
ref as fbRef,
set,
update,
} from "@firebase/database";
import {
ref,
watch,
onMounted,
onBeforeUnmount,
Ref,
computed,
} from "@vue/runtime-dom";
import { getDatabase, onValue, push, ref as fbRef, set, update } from "@firebase/database";
import { ref, watch, onMounted, onBeforeUnmount, Ref, computed } from "@vue/runtime-dom";
import { getUsername } from "../tools/databaseTools";
import { IListeners, IMovie, IWishlist } from "../types";
import { getAuth } from "@firebase/auth";
......@@ -30,6 +16,7 @@ export default function useWishlist() {
const listeners: IListeners = { wishlist: () => {} };
// Easier to simply overwrite entire wishlist in state
// Maybe just map to array so it is okay?
const fetchWishlist = () => {
listeners.wishlist = onValue(wishlistRef, (snapshot) => {
wishlist.value = snapshot.val();
......@@ -40,13 +27,14 @@ export default function useWishlist() {
onBeforeUnmount(() => unsubscibeListeners(listeners));
// const isEmpty = computed(() => wishlist.value.length === 0);
const isEmpty = computed(() => wishlist.value == null || Object.keys(wishlist.value).length === 0);
const isEmpty = computed(
() => wishlist.value == null || Object.keys(wishlist.value).length === 0
);
const addWish = (id: number) => {
push(wishlistRef, id);
};
//TODO: Lookinto if all mounting/unmounting can happen in the views for better loading?
const deleteWish = (deleteId: number) => {
if (Object.values(wishlist).length === 0) {
......@@ -55,9 +43,7 @@ export default function useWishlist() {
// const newList = wishlist.value.filter(({ id }) => deleteId !== id);
const newList = Object.fromEntries(
Object.entries(wishlist.value).filter(
([_, movieId]) => movieId !== deleteId
)
Object.entries(wishlist.value).filter(([_, movieId]) => movieId !== deleteId)
);
set(wishlistRef, newList);
};
......
......@@ -12,7 +12,7 @@ export default function useFilteredMovies(
isWishlist: boolean
) {
//TODO: Implement loading state
const filteredMovies = ref<IMovie[]>(movies.value);
const wishlistFilteredMovies = ref<IMovie[]>(movies.value);
const listeners: IListeners = { wishlist: () => {} };
const includesId = (id: number) => {
......@@ -21,7 +21,6 @@ export default function useFilteredMovies(
return Object.values(wishlist.value).includes(id);
};
const excWishlist = ({ id }: IMovie) => !includesId(id);
const incWishlist = ({ id }: IMovie) => includesId(id);
......@@ -29,13 +28,9 @@ export default function useFilteredMovies(
if (!wishlist.value || wishlist.value.length === 0) {
return console.log("nothing to filter");
}
filteredMovies.value = movies.value.filter(
isWishlist ? incWishlist : excWishlist
);
wishlistFilteredMovies.value = movies.value.filter(isWishlist ? incWishlist : excWishlist);
};
//TODO: add search query
// Hack, shouldn't it change when ever the ref changed?
// So shouldn't have to excplitely use watch
watch(movies, filterMovies);
......@@ -43,5 +38,5 @@ export default function useFilteredMovies(
watch(wishlist, filterMovies);
onBeforeUnmount(() => unsubscibeListeners(listeners));
return { filteredMovies };
return { wishlistFilteredMovies };
}
import type { Unsubscribe } from "@firebase/util";
export interface IMovie {
export interface IMovieRaw {
id: number;
genre: string;
year: number;
year: number | string;
title: string | number;
}
export interface IMovie extends IMovieRaw {
// extends Pick<IMovieRaw, "id" | "genre"> {
year: string;
title: string;
}
......
<template>
<h1>Movies</h1>
<input type="search" v-model="searchQuery" />
<div>
<div v-if="movies.length === 0">
<h3>Loading...</h3>
......@@ -22,11 +23,13 @@
</template>
<script setup lang="ts">
import { useFilteredMovies, useMovies, useWishlist } from "../hooks";
import { useWishlistMovies, useMovies, useWishlist, useMatchedMovies } from "../hooks";
const { movies } = useMovies();
const { wishlist, addWish } = useWishlist();
const { filteredMovies } = useFilteredMovies(movies, wishlist, false);
const { wishlistFilteredMovies } = useWishlistMovies(movies, wishlist, false);
const { searchQuery, moviesMatchingSearchQuery: filteredMovies } =
useMatchedMovies(wishlistFilteredMovies);
</script>
<style>
......
......@@ -21,11 +21,11 @@
</template>
<script setup lang="ts">
import { useRouter } from "vue-router";
import { useFilteredMovies, useMovies, useWishlist } from "../hooks";
import { useWishlistMovies, useMovies, useWishlist } from "../hooks";
const { movies } = useMovies();
const { wishlist, deleteWish, isEmpty } = useWishlist();
const { filteredMovies } = useFilteredMovies(movies, wishlist, true);
const { wishlistFilteredMovies: filteredMovies } = useWishlistMovies(movies, wishlist, true);
const router = useRouter();
const redirect = () => router.push({ name: "movies" });
......
......@@ -515,6 +515,11 @@
dependencies:
mini-svg-data-uri "^1.2.3"
"@types/lodash@^4.14.178":
version "4.14.178"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8"
integrity sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==
"@types/long@^4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
......@@ -1500,6 +1505,11 @@ lodash.camelcase@^4.3.0:
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
long@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment