243 lines
8.9 KiB
TypeScript
243 lines
8.9 KiB
TypeScript
import { ChangeEvent, TargetedEvent, useEffect, useState } from "preact/compat";
|
|
import { getListRecentLocationsRatingsService, getProvincesService, getRegenciesService } from "../../services";
|
|
import { LocationInfo } from "../../domains/LocationInfo";
|
|
import { DropdownInput } from "../../components";
|
|
import { IndonesiaRegionsInfo, LocationType } from "../../types/common";
|
|
import { Regency, emptyRegency } from "../../domains";
|
|
import { Form } from './types';
|
|
import { enumKeys } from "../../utils";
|
|
import './style.css';
|
|
import { createLocationService } from "../../services/locations";
|
|
import { useSelector } from "react-redux";
|
|
import { UserRootState } from "../../store/type";
|
|
|
|
function AddLocation() {
|
|
const [recentLocations, setRecentLocations] = useState<Array<LocationInfo>>()
|
|
const [idnRegions, setIdnRegions] = useState<IndonesiaRegionsInfo>({
|
|
regencies: Array<Regency>(),
|
|
})
|
|
const [form, setForm] = useState<Form>({
|
|
name: '',
|
|
address: '',
|
|
google_maps_link: '',
|
|
location_type: LocationType.Beach,
|
|
regency: emptyRegency(),
|
|
thumbnails: [],
|
|
})
|
|
|
|
const user = useSelector((state: UserRootState) => state.auth)
|
|
|
|
const [pageState, setPageState] = useState({
|
|
regency_form_error: false,
|
|
})
|
|
|
|
async function getRecentLocations() {
|
|
try {
|
|
const locations = await getListRecentLocationsRatingsService(9)
|
|
setRecentLocations(locations.data)
|
|
// setIsLoading(false)
|
|
} catch (error) {
|
|
console.log(error)
|
|
}
|
|
}
|
|
|
|
|
|
async function getRegions() {
|
|
try {
|
|
const provinces = await getProvincesService();
|
|
const regencies = await getRegenciesService();
|
|
|
|
setIdnRegions({
|
|
provinces: provinces.data,
|
|
regencies: regencies.data
|
|
})
|
|
|
|
} catch (error) {
|
|
console.log(error)
|
|
}
|
|
}
|
|
|
|
|
|
async function onSubmitForm(e: TargetedEvent) {
|
|
e.preventDefault();
|
|
|
|
if(form.regency.regency_name === '') {
|
|
setPageState({ regency_form_error: true })
|
|
return
|
|
}
|
|
|
|
let tempThumbnailArr: Array<File> = [];
|
|
let formData = new FormData();
|
|
|
|
form.thumbnails.forEach(x => {
|
|
tempThumbnailArr.push(x.file)
|
|
})
|
|
|
|
formData.append("address", form.address);
|
|
formData.append("location_type", form.location_type);
|
|
formData.append("name", form.name);
|
|
formData.append("regency_id", form.regency.id.toString());
|
|
formData.append("submitted_by", user.id.toString());
|
|
formData.append("google_maps_link", form.google_maps_link);
|
|
|
|
for(let i = 0; i < tempThumbnailArr.length; i++) {
|
|
formData.append("thumbnail", tempThumbnailArr[i])
|
|
}
|
|
|
|
try {
|
|
await createLocationService(formData)
|
|
alert("Location Added")
|
|
|
|
} catch(error) {
|
|
console.log(error)
|
|
}
|
|
}
|
|
|
|
function onChangeUploadImage(e: TargetedEvent) {
|
|
e.preventDefault()
|
|
let event = e.target as HTMLInputElement;
|
|
const files = Array.from(event.files as ArrayLike<File>);
|
|
|
|
const result = files.filter((x) => {
|
|
if (x.type === "image/jpg" || x.type === "image/png" || x.type === "image/jpeg") {
|
|
return true
|
|
}
|
|
return false
|
|
}).map(v => {
|
|
let ret = {
|
|
file: v,
|
|
url: URL.createObjectURL(v)
|
|
}
|
|
return ret
|
|
})
|
|
|
|
setForm({ ...form, thumbnails: result })
|
|
}
|
|
|
|
function onDeleteSelectedThumbnail(e: TargetedEvent, idx: number) {
|
|
e.preventDefault();
|
|
|
|
// remove image from FileList
|
|
const dt = new DataTransfer();
|
|
const tempInput = document.getElementById('imageUpload')!;
|
|
const input = tempInput as HTMLInputElement;
|
|
const { files } = input;
|
|
|
|
for (let i = 0; i < files!.length; i++) {
|
|
const file = files![i]
|
|
if (idx !== i)
|
|
dt.items.add(file)
|
|
}
|
|
|
|
input.files = dt.files
|
|
|
|
let thumbnails = form.thumbnails.filter((_, index) => index != idx);
|
|
setForm({ ...form, thumbnails: thumbnails })
|
|
}
|
|
|
|
function onChangeFormInput(e: ChangeEvent) {
|
|
let event = e.target as HTMLInputElement;
|
|
setForm({ ...form, [event.name]: event.value })
|
|
}
|
|
|
|
function onDeleteAllThumbnails(e: TargetedEvent) {
|
|
e.preventDefault();
|
|
|
|
const dt = new DataTransfer();
|
|
const tempInput = document.getElementById('imageUpload');
|
|
const input = tempInput as HTMLInputElement;
|
|
|
|
dt.items.clear();
|
|
input.files = dt.files
|
|
|
|
setForm({ ...form, thumbnails: [] })
|
|
}
|
|
|
|
function onChangeRegencyDropdownInput(val: Regency) {
|
|
setPageState({ ...pageState, regency_form_error: false })
|
|
setForm({ ...form, regency: val })
|
|
}
|
|
|
|
|
|
useEffect(() => {
|
|
getRecentLocations()
|
|
getRegions()
|
|
}, [])
|
|
|
|
return (
|
|
<div className={'content main-content'}>
|
|
<div style={{ tableLayout: 'fixed', display: 'table', width: '100%' }}>
|
|
<div style={{ textAlign: 'left', padding: '20px 30px', maxWidth: 1096, minWidth: 680, display: 'table-cell', position: 'relative', verticalAlign: 'top', width: '100%' }}>
|
|
<h1 className={'text-3xl mb-5 font-bold'}>Add New Location</h1>
|
|
<div style={{ backgroundColor: '#2f3136', padding: 10, margin: '0 0 25px' }}>
|
|
<form onSubmit={onSubmitForm}>
|
|
<span className={'block mt-2 text-sm mb-2'}>Location Name <span className={'text-error'}>*</span></span>
|
|
<input className={'bg-primary text-sm input-text'} type={'text'} onChange={onChangeFormInput} name={'name'} value={form.name} required />
|
|
<span className={'block mt-2 text-sm mb-2'}>Address <span className={'text-error'}>*</span></span>
|
|
<input className={'bg-primary text-sm input-text'} type={'text'} onChange={onChangeFormInput} name={'address'} value={form.address} required />
|
|
<label className={'block text-sm mt-2 mb-2'} for="location_type">Location Category</label>
|
|
<select className={'bg-primary p-1'} name="location_type" id="location_type">
|
|
{ enumKeys(LocationType).map(x => (
|
|
<option value={LocationType[x]}>{LocationType[x]}</option>
|
|
))
|
|
}
|
|
</select>
|
|
<span className={'block mt-2 text-sm mb-2'}>Kota / Kabupaten <span className={'text-error'}>*</span> <span className={`text-xs text-error ${!pageState.regency_form_error && 'hidden'}`}> (regency mustn't be empty)</span></span>
|
|
<DropdownInput
|
|
isSearchable={true}
|
|
onChange={(val: Regency) => onChangeRegencyDropdownInput(val)}
|
|
labelPropsName={"regency_name"}
|
|
options={idnRegions.regencies!}
|
|
placeholder={''}
|
|
/>
|
|
<span className={'block mt-2 text-sm mb-2'}>Google Maps Link <span className={'text-error'}>*</span></span>
|
|
<input className={'bg-primary text-sm input-text'} type={'text'} onChange={onChangeFormInput} name={'google_maps_link'} value={form.google_maps_link} required />
|
|
<span className={'block mt-2 text-sm mb-2'}>Thumbnails</span>
|
|
<input id={'imageUpload'} className={'inputfile'} type="file" accept={'image/*'} multiple onChange={onChangeUploadImage} />
|
|
<label for={'imageUpload'}>Choose File(s)</label>
|
|
<div style={{ clear: 'both' }} />
|
|
{form.thumbnails.length > 0 &&
|
|
form.thumbnails.map((x, idx) => (
|
|
<div className={'mr-3 font-bold'} style={{ width: 150, display: 'inline-block', textAlign: 'right', fontSize: 20 }}>
|
|
<a onClick={(e) => onDeleteSelectedThumbnail(e, idx)}>
|
|
x
|
|
</a>
|
|
<img
|
|
loading={'lazy'}
|
|
src={x.url}
|
|
className={'mt-1'}
|
|
style={{ aspectRatio: '1/1', objectFit: 'cover' }}
|
|
/>
|
|
</div>
|
|
))
|
|
}
|
|
{form.thumbnails.length > 0 &&
|
|
<a className={'block mt-2'} onClick={onDeleteAllThumbnails}>Delete All Thumbnails</a>
|
|
}
|
|
|
|
<input type={'submit'} value={'Submit'} className={'block p-1 text-sm text-primary mt-4'} style={{ backgroundColor: '#a8adb3', letterSpacing: .5, width: 75 }} />
|
|
</form>
|
|
<span className={'mt-5 text-sm font-bold block'}>NOTE: LOCATION SUBMISSION MAY BE EDITED BY MODERATOR SO DON'T PUT STUPID ASS THUMBNAILS YOU 1 CENT DOORKNOB</span>
|
|
</div>
|
|
</div>
|
|
<div style={{ display: 'table-cell', position: 'relative', verticalAlign: 'top', width: 345, textAlign: 'left', padding: '15px 0' }}>
|
|
<p>Recently added locations</p>
|
|
{recentLocations?.map(x => (
|
|
<div style={{ width: '32%', display: 'inline-block', padding: '1px 1%' }}>
|
|
<a href={'#'} title={x.name}>
|
|
<img
|
|
loading={'lazy'}
|
|
src={x.thumbnail ? x.thumbnail : ""}
|
|
alt={x.name}
|
|
style={{ aspectRatio: '1/1' }}
|
|
/>
|
|
</a>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default AddLocation; |