Skip to content

Commit

Permalink
Reviews feature parity (#179)
Browse files Browse the repository at this point in the history
* Change gallery view to use table for rendering

* Support delete in both views

* feat: Add sorting pills on gallery view

* feat: default gallery on mobile

* test fixes

* fix: clear local storage in test
  • Loading branch information
cole-adams authored Dec 9, 2024
1 parent d166d81 commit 94d33fc
Show file tree
Hide file tree
Showing 14 changed files with 457 additions and 155 deletions.
60 changes: 60 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
},
"dependencies": {
"@cubos/kysely-cockroach": "^1.0.0",
"@headlessui/vue": "^1.7.22",
"@mdi/js": "^7.1.96",
"@netlify/functions": "^1.3.0",
"@tanstack/query-persist-client-core": "^4.29.7",
Expand Down
8 changes: 8 additions & 0 deletions src/augmentations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,12 @@ declare module "@tanstack/vue-table" {
interface ColumnMeta {
class?: string;
}

interface HeaderContext {
meta?: Record<string, unknown>;
}

interface CellContext {
meta?: Record<string, unknown>;
}
}
159 changes: 147 additions & 12 deletions src/features/reviews/components/GalleryView.vue
Original file line number Diff line number Diff line change
@@ -1,32 +1,167 @@
<template>
<div class="md:px-6">
<div class="relative mb-4 flex w-min gap-2">
<Listbox v-model="selectedSort">
<ListboxButton
class="flex items-center whitespace-nowrap rounded-full border border-white px-4 py-1"
><span>Sort By</span><mdicon name="chevron-down"
/></ListboxButton>
<ListboxOptions
class="absolute z-10 rounded-md border border-white bg-background"
>
<ListboxOption
v-for="header in getSortableColumns()"
:key="header.id"
:value="header.id"
class="min-w-32 cursor-pointer px-2 py-1 text-left hover:bg-lowBackground"
>
<FlexRender
:render="header.column.columnDef.header"
:props="{
...header.getContext(),
meta: { size: 'sm', showName: true },
}"
/>
</ListboxOption>
</ListboxOptions>
</Listbox>

<div
v-if="sortState[0]"
class="flex items-center whitespace-nowrap rounded-full border border-white px-4 py-1"
>
<FlexRender
:render="reviewTable.getColumn(sortState[0].id)?.columnDef.header"
:props="{ meta: { showName: true, size: 'sm' } }"
/>
<mdicon
:name="sortState[0].desc ? 'chevron-down' : 'chevron-up'"
class="ml-2 cursor-pointer"
@click="reverseSort"
/>
</div>
<div
v-if="sortState[0]"
class="flex cursor-pointer items-center whitespace-nowrap rounded-full border border-white px-4 py-1"
@click="selectedSort = undefined"
>
Clear
<mdicon name="close" />
</div>
</div>

<transition-group
tag="div"
leave-active-class="absolute hidden"
enter-from-class="opacity-0"
leave-to-class="opacity-0"
class="grid grid-cols-auto justify-items-center"
>
<ReviewCard
v-for="review in reviews"
:key="review.id"
class="transition-all ease duration-500"
:review="review"
:members="members"
:movie-title="review.title"
:movie-poster-url="review.imageUrl ?? ''"
/>
<MoviePosterCard
v-for="row in reviewTable.getRowModel().rows"
:key="row.id"
:movie-title="row.renderValue('title')"
:movie-poster-url="row.renderValue('imageUrl')"
class="ease transition-all duration-500"
show-delete
@delete="deleteReview(row.original.id)"
>
<div class="mb-2 text-sm">
<FlexRender
:render="reviewTable.getColumn('createdDate')?.columnDef.cell"
:props="getCell(row, 'createdDate')?.getContext()"
/>
</div>
<div class="grid grid-cols-2 gap-2">
<div
v-for="cell in getVisibleCells(row)"
:key="cell.id"
class="flex items-center rounded-3xl bg-lowBackground"
>
<FlexRender
:render="cell.column.columnDef.header"
:props="{ ...cell.getContext(), meta: { size: 'sm' } }"
/>
<div class="flex-grow text-sm">
<FlexRender
:render="cell.column.columnDef.cell"
:props="{ ...cell.getContext(), meta: { size: 'sm' } }"
/>
</div>
</div>
</div>
</MoviePosterCard>
</transition-group>
</div>
</template>

<script setup lang="ts">
import {
Listbox,
ListboxButton,
ListboxOption,
ListboxOptions,
} from "@headlessui/vue";
import { FlexRender, Row, Table } from "@tanstack/vue-table";
import { computed } from "vue";
import MoviePosterCard from "@/common/components/MoviePosterCard.vue";
import { Member } from "@/common/types/club";
import { DetailedReviewListItem } from "@/common/types/lists";
import ReviewCard from "@/features/reviews/components/ReviewCard.vue";
const { reviews, members: members } = defineProps<{
reviews: DetailedReviewListItem[];
const props = defineProps<{
reviewTable: Table<DetailedReviewListItem>;
deleteReview: (workId: string) => void;
members: Member[];
}>();
const CUSTOM_RENDERED_COLUMNS = ["title", "imageUrl", "createdDate"];
const NON_SORTABLE_COLUMNS = ["imageUrl"];
const getVisibleCells = (row: Row<DetailedReviewListItem>) => {
return row.getVisibleCells().filter((cell) => {
return !CUSTOM_RENDERED_COLUMNS.includes(cell.column.id);
});
};
const getSortableColumns = () => {
return props.reviewTable.getFlatHeaders().filter((header) => {
return !NON_SORTABLE_COLUMNS.includes(header.id);
});
};
const getCell = (row: Row<DetailedReviewListItem>, columnId: string) => {
return row.getVisibleCells().find((cell) => cell.column.id === columnId);
};
const reverseSort = () => {
const currentSort = sortState.value[0];
if (!currentSort) {
return;
}
props.reviewTable.setSorting([
{
id: currentSort.id,
desc: !currentSort.desc,
},
]);
};
const sortState = computed(() => props.reviewTable.getState().sorting);
const selectedSort = computed<string | undefined>({
get: () => sortState.value[0]?.id,
set: (value: string | undefined) => {
if (!value) {
props.reviewTable.setSorting([]);
return;
}
props.reviewTable.setSorting([
{
id: value,
desc: true,
},
]);
},
});
</script>
49 changes: 0 additions & 49 deletions src/features/reviews/components/ReviewCard.vue

This file was deleted.

4 changes: 3 additions & 1 deletion src/features/reviews/components/ReviewScore.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
ref="scoreInput"
v-model="scoreModel"
aria-label="Score"
class="w-10 rounded-lg border border-gray-300 bg-background p-2 text-center outline-none focus:border-primary"
class="rounded-lg border border-gray-300 bg-background text-center outline-none focus:border-primary"
:class="{ 'w-10 p-2': size !== 'sm', 'w-8': size === 'sm' }"
@blur="isInputOpen = false"
@keypress.enter="submitScore(parseFloat(scoreModel))"
/>
Expand All @@ -39,6 +40,7 @@ const props = defineProps<{
workId: string;
score?: number;
reviewId?: string;
size?: string;
}>();
const { data: user } = useUser();
Expand Down
Loading

0 comments on commit 94d33fc

Please sign in to comment.