feat(pages): add create url

This commit is contained in:
diced 2021-09-25 18:00:00 -07:00
parent f1c46da47d
commit 5818440721
No known key found for this signature in database
GPG key ID: 85AB64C74535D76E

View file

@ -1,20 +1,44 @@
import React, { useEffect, useState } from 'react';
import { Grid, Card, CardHeader, Box, Typography, IconButton, Link } from '@material-ui/core';
import { ContentCopy as CopyIcon, DeleteForever as DeleteIcon } from '@material-ui/icons';
import { Grid, Card, CardHeader, Box, Typography, IconButton, Link, Dialog, DialogContent, DialogActions, Button, DialogTitle, TextField } from '@material-ui/core';
import { ContentCopy as CopyIcon, DeleteForever as DeleteIcon, Add as AddIcon } from '@material-ui/icons';
import Backdrop from 'components/Backdrop';
import useFetch from 'hooks/useFetch';
import Alert from 'components/Alert';
import copy from 'copy-to-clipboard';
import { useFormik } from 'formik';
import { useStoreSelector } from 'lib/redux/store';
import * as yup from 'yup';
function TextInput({ id, label, formik, ...other }) {
return (
<TextField
id={id}
name={id}
label={label}
value={formik.values[id]}
onChange={formik.handleChange}
error={formik.touched[id] && Boolean(formik.errors[id])}
helperText={formik.touched[id] && formik.errors[id]}
variant='standard'
fullWidth
sx={{ pb: 0.5 }}
{...other}
/>
);
}
export default function Urls() {
const user = useStoreSelector(state => state.user);
const [loading, setLoading] = useState(true);
const [urls, setURLS] = useState([]);
const [open, setOpen] = useState(false);
const [createOpen, setCreateOpen] = useState(false);
const [severity, setSeverity] = useState('success');
const [message, setMessage] = useState('Deleted');
const updatePages = async () => {
const updateURLs = async () => {
setLoading(true);
const urls = await useFetch('/api/user/urls');
@ -34,7 +58,7 @@ export default function Urls() {
setOpen(true);
}
updatePages();
updateURLs();
};
const copyURL = u => {
@ -44,8 +68,55 @@ export default function Urls() {
setOpen(true);
};
const formik = useFormik({
initialValues: {
url: '',
vanity: '',
},
validationSchema: yup.object({
}),
onSubmit: async (values) => {
const cleanURL = values.url.trim();
const cleanVanity = values.vanity.trim();
if (cleanURL === '') return formik.setFieldError('username', 'Username can\'t be nothing');
const data = {
url: cleanURL,
vanity: cleanVanity === '' ? null : cleanVanity,
};
setCreateOpen(false);
setLoading(true);
const res = await fetch('/api/shorten', {
method: 'POST',
headers: {
'Authorization': user.token,
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
const json = await res.json();
if (json.error) {
setSeverity('error');
setMessage('Could\'nt create URL: ' + json.error);
setOpen(true);
} else {
setSeverity('success');
setMessage('Copied URL: ' + json.url);
copy(json.url);
setOpen(true);
setCreateOpen(false);
updateURLs();
}
setLoading(false);
},
});
useEffect(() => {
updatePages();
updateURLs();
}, []);
return (
@ -53,6 +124,22 @@ export default function Urls() {
<Backdrop open={loading}/>
<Alert open={open} setOpen={setOpen} message={message} severity={severity} />
<Dialog open={createOpen} onClose={() => setCreateOpen(false)}>
<DialogTitle>Shorten URL</DialogTitle>
<form onSubmit={formik.handleSubmit}>
<DialogContent>
<TextInput id='url' label='URL' formik={formik} />
<TextInput id='vanity' label='Vanity' formik={formik} />
</DialogContent>
<DialogActions>
<Button onClick={() => setCreateOpen(false)} color='inherit' autoFocus>Cancel</Button>
<Button type='submit' color='inherit'>
Create
</Button>
</DialogActions>
</form>
</Dialog>
{!urls.length ? (
<Box
display='flex'
@ -61,9 +148,9 @@ export default function Urls() {
pt={2}
pb={3}
>
<Typography variant='h4'>No URLs</Typography>
<Typography variant='h4' sx={{ mb: 1 }}>No URLs <IconButton onClick={() => setCreateOpen(true)}><AddIcon/></IconButton></Typography>
</Box>
) : <Typography variant='h4'>URLs</Typography>}
) : <Typography variant='h4' sx={{ mb: 1 }}>URLs <IconButton onClick={() => setCreateOpen(true)}><AddIcon/></IconButton></Typography>}
<Grid container spacing={2}>
{urls.length ? urls.map(url => (