feat(pages): add create url
This commit is contained in:
parent
f1c46da47d
commit
5818440721
1 changed files with 94 additions and 7 deletions
|
@ -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 => (
|
||||
|
|
Loading…
Reference in a new issue