diff --git a/zimui/src/components/video/VideoCard.vue b/zimui/src/components/video/VideoCard.vue
index efbf2465..d90ad680 100644
--- a/zimui/src/components/video/VideoCard.vue
+++ b/zimui/src/components/video/VideoCard.vue
@@ -13,6 +13,7 @@ const { smAndDown } = useDisplay()
const props = defineProps<{
video: VideoPreview
playlistSlug?: string
+ carouselMode?: boolean
}>()
// Set the maximum length of the title based on the screen size
@@ -53,7 +54,7 @@ onMounted(async () => {
>
-
+
{
{{ truncatedTitle }}
diff --git a/zimui/src/components/video/VideoList.vue b/zimui/src/components/video/VideoList.vue
new file mode 100644
index 00000000..4ae19075
--- /dev/null
+++ b/zimui/src/components/video/VideoList.vue
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/zimui/src/components/video/carousel/VideoCarousel.vue b/zimui/src/components/video/carousel/VideoCarousel.vue
new file mode 100644
index 00000000..3aace683
--- /dev/null
+++ b/zimui/src/components/video/carousel/VideoCarousel.vue
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ View All mdi-chevron-right-circle-outline
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/zimui/src/components/video/carousel/VideoCarouselInfo.vue b/zimui/src/components/video/carousel/VideoCarouselInfo.vue
new file mode 100644
index 00000000..9b8b1b2d
--- /dev/null
+++ b/zimui/src/components/video/carousel/VideoCarouselInfo.vue
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+ {{ props.title }}
+
+
+
+
+
+
+ Play all
+
+
+
+
+
+ {{ props.count }} {{ props.countText }}
+
+
+
+
+
+
+
diff --git a/zimui/src/stores/main.ts b/zimui/src/stores/main.ts
index ffa396b3..375c7556 100644
--- a/zimui/src/stores/main.ts
+++ b/zimui/src/stores/main.ts
@@ -1,7 +1,7 @@
import { defineStore } from 'pinia'
import axios, { AxiosError } from 'axios'
import type { Channel } from '@/types/Channel'
-import type { LoopOptions, Playlist, Playlists } from '@/types/Playlists'
+import type { HomePlaylists, LoopOptions, Playlist, Playlists } from '@/types/Playlists'
import type { Video } from '@/types/Videos'
export type RootState = {
@@ -65,6 +65,25 @@ export const useMainStore = defineStore('main', {
}
)
},
+ async fetchHomePlaylists() {
+ this.isLoading = true
+ this.errorMessage = ''
+ this.errorDetails = ''
+
+ return axios.get('./home_playlists.json').then(
+ (response) => {
+ this.isLoading = false
+ return response.data as HomePlaylists
+ },
+ (error) => {
+ this.isLoading = false
+ this.errorMessage = 'Failed to load home playlists.'
+ if (error instanceof AxiosError) {
+ this.handleAxiosError(error)
+ }
+ }
+ )
+ },
async fetchPlaylists() {
this.isLoading = true
this.errorMessage = ''
diff --git a/zimui/src/types/Playlists.ts b/zimui/src/types/Playlists.ts
index 2f19217c..3a0d0411 100644
--- a/zimui/src/types/Playlists.ts
+++ b/zimui/src/types/Playlists.ts
@@ -3,6 +3,7 @@ import type { VideoPreview } from './Videos'
export interface Playlist {
id: string
+ slug: string
author: Author
title: string
description: string
@@ -24,6 +25,10 @@ export interface Playlists {
playlists: PlaylistPreview[]
}
+export interface HomePlaylists {
+ playlists: Playlist[]
+}
+
export enum LoopOptions {
off = 'off',
loopVideo = 'loop-video',
diff --git a/zimui/yarn.lock b/zimui/yarn.lock
index 04152254..ce120737 100644
--- a/zimui/yarn.lock
+++ b/zimui/yarn.lock
@@ -4722,6 +4722,11 @@ vue-tsc@^2.1.6:
"@vue/language-core" "2.1.6"
semver "^7.5.4"
+vue3-carousel@^0.3.4:
+ version "0.3.4"
+ resolved "https://registry.yarnpkg.com/vue3-carousel/-/vue3-carousel-0.3.4.tgz#8ef6d6b592385b7f8e97fcd508a3f4db29a2391e"
+ integrity sha512-jImUDbQa/9pELxUQdkflUPXL94V+iQZaOPUxWDBKSffCuxhYcV3sDM40pxoiYxUxXoNCDLUF4u9Ug6Xjdt4nkA==
+
vue@^3.5.4:
version "3.5.4"
resolved "https://registry.yarnpkg.com/vue/-/vue-3.5.4.tgz#0e5935e8b1e5505d484aee732b72c6e77c7567fd"