Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions inertia/components/add-media-dialog.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import type { Meta, StoryObj } from '@storybook/react'
import { action } from 'storybook/actions'
import { AddMediaDialog } from './add-media-dialog'
import type { QualityProfile } from './add-media-dialog'

const sampleProfiles: QualityProfile[] = [
{ id: '1', name: 'HD-1080p', mediaType: 'movie' },
{ id: '2', name: 'HD-720p', mediaType: 'movie' },
{ id: '3', name: 'SD', mediaType: 'movie' },
]

const meta: Meta<typeof AddMediaDialog> = {
component: AddMediaDialog,
tags: ['autodocs'],
args: {
open: true,
onOpenChange: action('onOpenChange'),
onAdd: action('onAdd'),
qualityProfiles: sampleProfiles,
},
argTypes: {
mediaType: {
control: 'select',
options: ['artist', 'album', 'movie', 'tvshow', 'author', 'book'],
},
loading: { control: 'boolean' },
adding: { control: 'boolean' },
},
}
export default meta

type Story = StoryObj<typeof AddMediaDialog>

export const Movie: Story = {
args: {
mediaType: 'movie',
title: 'Inception',
description: 'Add this movie to your library and start monitoring for downloads.',
},
}

export const Album: Story = {
args: {
mediaType: 'album',
title: 'Dark Side of the Moon',
description: 'Add this album to your library.',
qualityProfiles: [
{ id: '1', name: 'Lossless', mediaType: 'album' },
{ id: '2', name: 'High Quality', mediaType: 'album' },
{ id: '3', name: 'Standard', mediaType: 'album' },
],
},
}

export const TvShowWithEpisodes: Story = {
args: {
mediaType: 'tvshow',
title: 'Breaking Bad',
description: 'Add this TV show to your library.',
episodeSelectionSummary: '62 of 62 episodes selected (5 seasons)',
onChangeEpisodeSelection: action('onChangeEpisodeSelection'),
},
}

export const AuthorWithBooks: Story = {
args: {
mediaType: 'author',
title: 'Frank Herbert',
description: 'Add this author to your library.',
showAddBooksOption: true,
},
}

export const Loading: Story = {
args: {
mediaType: 'movie',
title: 'Inception',
description: 'Add this movie to your library.',
loading: true,
},
}

export const Adding: Story = {
args: {
mediaType: 'movie',
title: 'Inception',
description: 'Add this movie to your library.',
adding: true,
},
}
53 changes: 53 additions & 0 deletions inertia/components/confirm-dialog.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { Meta, StoryObj } from '@storybook/react'
import { action } from 'storybook/actions'
import { ConfirmDialog } from './confirm-dialog'

const meta: Meta<typeof ConfirmDialog> = {
component: ConfirmDialog,
tags: ['autodocs'],
args: {
close: action('close'),
handleConfirm: action('handleConfirm'),
loading: false,
},
}
export default meta

type Story = StoryObj<typeof ConfirmDialog>

export const Default: Story = {
args: {
state: {
open: true,
title: 'Remove from library?',
description: 'This action cannot be undone. The item will be removed from your library.',
confirmLabel: 'Remove',
loadingLabel: 'Removing...',
},
},
}

export const Loading: Story = {
args: {
loading: true,
state: {
open: true,
title: 'Delete all files?',
description: 'This will permanently delete all selected files from disk.',
confirmLabel: 'Delete All',
loadingLabel: 'Deleting...',
},
},
}

export const RefreshLibrary: Story = {
args: {
state: {
open: true,
title: 'Refresh library?',
description: 'This will rescan all media folders and update your library. This may take a while.',
confirmLabel: 'Refresh',
loadingLabel: 'Refreshing...',
},
},
}
62 changes: 62 additions & 0 deletions inertia/components/error-boundary.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { Meta, StoryObj } from '@storybook/react'
import { ErrorBoundary } from './error-boundary'

const meta: Meta<typeof ErrorBoundary> = {
component: ErrorBoundary,
tags: ['autodocs'],
parameters: {
layout: 'centered',
},
}
export default meta

type Story = StoryObj<typeof ErrorBoundary>

function ThrowError(): never {
throw new Error('Test error for Storybook')
}

export const Default: Story = {
render: () => (
<ErrorBoundary>
<ThrowError />
</ErrorBoundary>
),
}

export const FullPage: Story = {
parameters: {
layout: 'fullscreen',
},
render: () => (
<ErrorBoundary fullPage>
<ThrowError />
</ErrorBoundary>
),
}

export const CustomFallback: Story = {
render: () => (
<ErrorBoundary
fallback={
<div className="p-8 text-center text-muted-foreground">
Custom error fallback content
</div>
}
>
<ThrowError />
</ErrorBoundary>
),
}

export const NoError: Story = {
render: () => (
<ErrorBoundary>
<div className="p-8 text-center">
<p className="text-sm text-muted-foreground">
This content renders normally when there is no error.
</p>
</div>
</ErrorBoundary>
),
}
65 changes: 65 additions & 0 deletions inertia/components/library/delete-media-dialog.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import type { Meta, StoryObj } from '@storybook/react'
import { action } from 'storybook/actions'
import { DeleteMediaDialog } from './delete-media-dialog'

const meta: Meta<typeof DeleteMediaDialog> = {
component: DeleteMediaDialog,
tags: ['autodocs'],
args: {
open: true,
onOpenChange: action('onOpenChange'),
onConfirm: () => new Promise((r) => setTimeout(r, 1000)),
},
argTypes: {
mode: { control: 'select', options: ['remove', 'deleteFile'] },
hasFile: { control: 'boolean' },
},
}
export default meta

type Story = StoryObj<typeof DeleteMediaDialog>

export const RemoveWithFile: Story = {
args: {
title: 'Inception',
mediaType: 'movie',
hasFile: true,
mode: 'remove',
},
}

export const RemoveWithoutFile: Story = {
args: {
title: 'The Matrix',
mediaType: 'movie',
hasFile: false,
mode: 'remove',
},
}

export const DeleteFileMode: Story = {
args: {
title: 'Dark Side of the Moon',
mediaType: 'album',
hasFile: true,
mode: 'deleteFile',
},
}

export const BookRemove: Story = {
args: {
title: 'Dune',
mediaType: 'book',
hasFile: true,
mode: 'remove',
},
}

export const EpisodeDeleteFile: Story = {
args: {
title: 'S01E01 - Pilot',
mediaType: 'episode',
hasFile: true,
mode: 'deleteFile',
},
}
72 changes: 72 additions & 0 deletions inertia/components/library/download-progress-card.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import type { Meta, StoryObj } from '@storybook/react'
import { DownloadProgressCard } from './download-progress-card'
import type { ActiveDownloadInfo } from '@/hooks/use_active_downloads'

const meta: Meta<typeof DownloadProgressCard> = {
component: DownloadProgressCard,
tags: ['autodocs'],
decorators: [
(Story) => (
<div className="w-[400px]">
<Story />
</div>
),
],
}
export default meta

type Story = StoryObj<typeof DownloadProgressCard>

const downloading: ActiveDownloadInfo = {
progress: 45,
status: 'downloading',
title: 'Inception.2010.1080p.BluRay.x264',
size: 8_589_934_592,
remaining: 4_724_464_025,
eta: 3725,
downloadClient: 'SABnzbd',
}

const almostDone: ActiveDownloadInfo = {
progress: 92,
status: 'downloading',
title: 'Breaking.Bad.S01E01.720p',
size: 1_073_741_824,
remaining: 85_899_345,
eta: 120,
downloadClient: 'SABnzbd',
}

const importing: ActiveDownloadInfo = {
progress: 100,
status: 'importing',
title: 'Dark.Side.of.the.Moon.FLAC',
size: 734_003_200,
remaining: 0,
eta: null,
downloadClient: 'SABnzbd',
}

export const SingleDownload: Story = {
args: {
downloads: [downloading],
},
}

export const MultipleDownloads: Story = {
args: {
downloads: [downloading, almostDone, importing],
},
}

export const Importing: Story = {
args: {
downloads: [importing],
},
}

export const Empty: Story = {
args: {
downloads: [],
},
}
Loading