Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: show media on light-box #33

Merged
merged 2 commits into from
Nov 19, 2022
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
8 changes: 8 additions & 0 deletions web/src/adapters/stores/item/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* eslint-disable import/prefer-default-export */
import create from 'zustand';

import { ItemWithURL } from '../../../domains/item';

type ItemState = { items: ItemWithURL[] };

export const useItemStore = create<ItemState>(() => ({ items: [] }));
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React from 'react';

import {
ArrowBack,
ChevronLeft,
ChevronRight,
CloudDownload,
DeleteForever,
} from '@mui/icons-material';
import { AppBar, Box, Button, CircularProgress, Dialog, IconButton, Toolbar } from '@mui/material';

import { ItemWithURL } from '../../../../../domains/item';

type Props = {
item: ItemWithURL;
loading: boolean;
onClose: () => void;
onDelete: () => void;
onDownload: () => void;
onNavigateNext?: () => void;
onNavigatePrev?: () => void;
};

export default function Lightbox({
item,
loading,
onClose,
onDelete,
onDownload,
onNavigateNext,
onNavigatePrev,
}: Props) {
return (
<Dialog
fullWidth
maxWidth={false}
onClose={onClose}
open
PaperProps={{ sx: { bgcolor: 'black', height: '100%' } }}
>
<Box alignItems="center" bgcolor="black" display="flex" height="100%" justifyContent="center">
<AppBar color="transparent" elevation={0} position="absolute">
<Toolbar>
<Box flexGrow={1}>
<Button
onClick={onClose}
size="large"
startIcon={<ArrowBack />}
sx={{ color: 'white' }}
>
戻る
</Button>
</Box>
<Box>
<IconButton onClick={onDownload} sx={{ color: 'white' }}>
{loading ? <CircularProgress color="inherit" size={20} /> : <CloudDownload />}
</IconButton>
<IconButton disabled={loading} onClick={onDelete} sx={{ color: 'white' }}>
<DeleteForever />
</IconButton>
</Box>
</Toolbar>
</AppBar>
<Box
alignItems="center"
display="flex"
height="100%"
justifyContent="space-between"
px={3}
width="100%"
>
<IconButton
disabled={loading || !onNavigateNext}
onClick={onNavigateNext}
sx={{ color: 'white' }}
>
<ChevronLeft fontSize="large" />
</IconButton>
<Box component="img" maxHeight="100%" src={item.url} />
<IconButton
disabled={loading || !onNavigatePrev}
onClick={onNavigatePrev}
sx={{ color: 'white' }}
>
<ChevronRight fontSize="large" />
</IconButton>
</Box>
</Box>
</Dialog>
);
}
48 changes: 23 additions & 25 deletions web/src/adapters/userInterface/components/pages/item/get/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import React, { useEffect, useState } from 'react';

import { CloudDownload } from '@mui/icons-material';
import { LoadingButton } from '@mui/lab';
import { Box, Button } from '@mui/material';
import { saveAs } from 'file-saver';
import { Navigate, useNavigate, useParams } from 'react-router-dom';

Expand All @@ -12,10 +9,13 @@ import { ItemWithURL } from '../../../../../../domains/item';
import itemRepository from '../../../../../repositories/item';
import mediumRepository from '../../../../../repositories/medium';
import { useAlertStore } from '../../../../../stores/alert';
import { useItemStore } from '../../../../../stores/item';
import Dialog from '../../../molecules/dialog/item/delete';
import Lightbox from '../../../organisms/lightbox';
import Loading from '../../loading';

export default function ItemGet() {
const { items } = useItemStore();
const { get: getItem, softDelete: softDeleteItem } = useItemUseCase(
itemRepository(),
mediumRepository()
Expand All @@ -25,16 +25,25 @@ export default function ItemGet() {
const { id } = useParams<{ id: string }>();
const [item, setItem] = useState<ItemWithURL | null>();
const [loading, setLoading] = useState(false);
const [nextId, setNextId] = useState<string>();
const [openDialog, setOpenDialog] = useState(false);
const [prevId, setPrevId] = useState<string>();

useEffect(() => {
if (id) {
getItem(id).then(setItem);
const index = items.findIndex((element) => element.id === id);
setNextId(items[index - 1]?.id);
setPrevId(items[index + 1]?.id);
} else {
navigate('/media');
}
}, [id]);

const navigateList = () => navigate('/media');
const navigateNext = nextId ? () => navigate(`/media/${nextId}`) : undefined;
const navigatePrev = prevId ? () => navigate(`/media/${prevId}`) : undefined;

const onDelete = async () => {
if (!id) return navigate('/media');

Expand All @@ -54,7 +63,7 @@ export default function ItemGet() {
});
};

const onSave = async () => {
const onDownload = async () => {
if (!item) return navigate('/media');

setLoading(true);
Expand All @@ -73,27 +82,16 @@ export default function ItemGet() {
if (!item) return <Navigate to="/media" />;
return (
<>
<Box display="flex" justifyContent="flex-end" mb={3}>
<LoadingButton
disableElevation
loading={loading}
onClick={onSave}
startIcon={<CloudDownload />}
sx={{ borderRadius: 2 }}
variant="contained"
>
ダウンロード
</LoadingButton>
</Box>
<Box pb={3}>
<Box component="img" src={item.url} />
<Box display="flex" justifyContent="flex-end" mt={3}>
<Button color="error" disabled={loading} onClick={toggleDialog} size="small">
このメディアを削除
</Button>
</Box>
<Dialog onClose={toggleDialog} onSubmit={onDelete} open={openDialog} />
</Box>
<Lightbox
item={item}
loading={loading}
onClose={navigateList}
onDelete={toggleDialog}
onDownload={onDownload}
onNavigateNext={navigateNext}
onNavigatePrev={navigatePrev}
/>
<Dialog onClose={toggleDialog} onSubmit={onDelete} open={openDialog} />
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@ import { Box, Button } from '@mui/material';
import { Link } from 'react-router-dom';

import useItemUseCase from '../../../../../../application/useCases/item';
import { ItemWithURL } from '../../../../../../domains/item';
import itemRepository from '../../../../../repositories/item';
import mediumRepository from '../../../../../repositories/medium';
import { useItemStore } from '../../../../../stores/item';
import ItemSectionList from '../../../organisms/sectionList/item';
import Loading from '../../loading';

export default function ItemList() {
const { items } = useItemStore();
const { subscribe } = useItemUseCase(itemRepository(), mediumRepository());
const [items, setItems] = useState<ItemWithURL[]>();
const [limit] = useState(100);

useEffect(() => {
const unsubscribe = subscribe(limit, setItems);
const unsubscribe = subscribe(limit, (nextItems) =>
useItemStore.setState({ items: nextItems })
);
return () => unsubscribe();
}, []);

if (typeof items === 'undefined') return <Loading />;
return (
<>
<Box display="flex" justifyContent="flex-end" mb={3}>
Expand Down