You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
3.5 KiB
JavaScript

import React, {useState, useEffect, useMemo, useRef} from 'react'
import {DateTime} from 'luxon'
import axios from 'axios'
import Link from 'next/link'
import {Button} from '@rmwc/button'
import ActionBar from '~/components/admin/actionBar'
import {Icon} from '@rmwc/icon'
import styles from '~/styles/imageGallery.module.css'
EditImages.getInitialProps = async ({ctx: {axios, query: {slug}}}) => {
const {data: item} = await axios.get(`/api/items/by-slug/${slug}`)
return {item}
}
export default function EditImages({item: _item}) {
const [item, setItem] = useState(_item)
const fileRef = useRef()
// Only re-sort images whenever item changes
const images = useMemo(() => item.images.slice(0).sort(
(a,b) => DateTime.fromISO(a.date_uploaded).diff(DateTime.fromISO(b.date_uploaded))
), [item])
async function selectImage(ev){
if(ev) ev.preventDefault()
fileRef.current.click()
}
useEffect(()=>{
fileRef.current.addEventListener('change', uploadImage)
return ()=>fileRef.current.removeEventListener('change', uploadImage)
}, [])
async function uploadImage(ev){
if(ev) ev.preventDefault()
const image = await readFileAsync(ev.target)
const {data: updatedItem} = await axios.post(`/api/items/${item.uuid}/images`, {image})
setItem(updatedItem)
}
function handleSetFeatured(image){
return async (ev) => {
if(ev) ev.preventDefault();
const {data: updatedItem} = await axios.post(`/api/images/${image.uuid}/featured`)
setItem(updatedItem)
}
}
function handleRemoveImage(image){
return async (ev) => {
if(ev) ev.preventDefault()
const {data: updatedItem} = await axios.delete(`/api/images/${image.uuid}`)
setItem(updatedItem)
}
}
return (
<>
<ActionBar title={`Editing images for "${item.name}"`}>
<Button outlined onClick={selectImage}>Add Image</Button>
</ActionBar>
<Link href={`/admin/items/${item.urlslug}`}><a><Button icon="arrow_left">Back to {item.name}</Button></a></Link>
<div className={styles.gallery}>
{images.map(image => (
<div key={image.uuid} className={styles.image}>
<img key={image.uuid} src={`/api/images/${image.uuid}/thumb`}/>
<div className={styles.details}>
<div>
<span>Uploaded {DateTime.fromISO(image.date_uploaded).toFormat('DD')}</span>
<span>by {image.uploader.email}</span>
</div>
<button title="Set Featured" onClick={handleSetFeatured(image)} className="buttonLink"><Icon icon={image.featured?"star":"star_outline"}/></button>
<button title="Remove Image" onClick={handleRemoveImage(image)} className="buttonLink"><Icon icon="delete"/></button>
</div>
</div>
))}
{!images.length ? (
<>
<p style={{marginTop: '100px'}}>No images added for this item.</p>
<Button outlined onClick={selectImage}>Add One!</Button>
</>
) : (
<p><Button outlined onClick={selectImage}>Add Image</Button></p>
)}
</div>
<input ref={fileRef} className={styles.upload} type="file" accept="image/*" />
</>
)
}
function readFileAsync(fileInput){
const reader = new FileReader()
return new Promise((resolve, reject) => {
reader.addEventListener('load', () => {
resolve(reader.result)
})
reader.addEventListener('error', reject)
reader.addEventListener('abort', reject)
reader.readAsDataURL(fileInput.files[0])
})
}