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
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])
|
|
})
|
|
}
|