import formatDistanceToNow from "date-fns/formatDistanceToNow"; import { CopyToClipboard } from "react-copy-to-clipboard"; import React, { FC, useState, useEffect } from "react"; import { useFormState } from "react-use-form-state"; import { Flex } from "reflexbox/styled-components"; import styled, { css } from "styled-components"; import QRCode from "qrcode.react"; import Link from "next/link"; import { useStoreActions, useStoreState } from "../store"; import { removeProtocol, withComma, errorMessage } from "../utils"; import { Checkbox, TextInput } from "./Input"; import { NavButton, Button } from "./Button"; import { Col, RowCenter } from "./Layout"; import Text, { H2, Span } from "./Text"; import { ifProp } from "styled-tools"; import Animation from "./Animation"; import { Colors } from "../consts"; import Tooltip from "./Tooltip"; import Table from "./Table"; import ALink from "./ALink"; import Modal from "./Modal"; import Icon from "./Icon"; import { useMessage } from "../hooks"; const Tr = styled(Flex).attrs({ as: "tr", px: [12, 12, 2] })``; const Th = styled(Flex)``; Th.defaultProps = { as: "th", flexBasis: 0, py: [12, 12, 3], px: [12, 12, 3] }; const Td = styled(Flex)<{ withFade?: boolean }>` position: relative; white-space: nowrap; ${ifProp( "withFade", css` :after { content: ""; position: absolute; right: 0; top: 0; height: 100%; width: 16px; background: linear-gradient(to left, white, white, transparent); } tr:hover &:after { background: linear-gradient( to left, ${Colors.TableRowHover}, ${Colors.TableRowHover}, transparent ); } ` )} `; Td.defaultProps = { as: "td", fontSize: [15, 16], alignItems: "center", flexBasis: 0, py: [12, 12, 3], px: [12, 12, 3] }; const Action = (props: React.ComponentProps) => ( ); const ogLinkFlex = { flexGrow: [1, 3, 7], flexShrink: [1, 3, 7] }; const createdFlex = { flexGrow: [1, 1, 3], flexShrink: [1, 1, 3] }; const shortLinkFlex = { flexGrow: [1, 1, 3], flexShrink: [1, 1, 3] }; const viewsFlex = { flexGrow: [0.5, 0.5, 1], flexShrink: [0.5, 0.5, 1], justifyContent: "flex-end" }; const actionsFlex = { flexGrow: [1, 1, 2.5], flexShrink: [1, 1, 2.5] }; interface Form { all: boolean; limit: string; skip: string; search: string; } const LinksTable: FC = () => { const isAdmin = useStoreState(s => s.auth.isAdmin); const links = useStoreState(s => s.links); const { get, deleteOne } = useStoreActions(s => s.links); const [tableMessage, setTableMessage] = useState("No links to show."); const [copied, setCopied] = useState([]); const [qrModal, setQRModal] = useState(-1); const [deleteModal, setDeleteModal] = useState(-1); const [deleteLoading, setDeleteLoading] = useState(false); const [deleteMessage, setDeleteMessage] = useMessage(); const [formState, { label, checkbox, text }] = useFormState
( { skip: "0", limit: "10", all: false }, { withIds: true } ); const options = formState.values; const linkToDelete = links.items[deleteModal]; useEffect(() => { get(options).catch(err => setTableMessage(err?.response?.data?.error)); }, [options.limit, options.skip, options.all]); const onSubmit = e => { e.preventDefault(); get(options); }; const onCopy = (index: number) => () => { setCopied([index]); setTimeout(() => { setCopied(s => s.filter(i => i !== index)); }, 1500); }; const onDelete = async () => { setDeleteLoading(true); try { await deleteOne({ id: linkToDelete.address, domain: linkToDelete.domain }); await get(options); setDeleteModal(-1); } catch (err) { setDeleteMessage(errorMessage(err)); } setDeleteLoading(false); }; const onNavChange = (nextPage: number) => () => { formState.setField("skip", (parseInt(options.skip) + nextPage).toString()); }; const Nav = ( {["10", "25", "50"].map(c => ( { formState.setField("limit", c); formState.setField("skip", "0"); }} > {c} ))} links.total } ml={12} px={2} > ); return (

Recent shortened links.

{Nav} {!links.items.length ? ( ) : ( <> {links.items.map((l, index) => ( ))} )} {Nav}
{isAdmin && ( )}
Original URL Created Short URL Views
{links.loading ? "Loading links..." : tableMessage}
{l.target} {`${formatDistanceToNow( new Date(l.created_at) )} ago`} {copied.includes(index) ? ( ) : ( )} {removeProtocol(l.link)} {withComma(l.visit_count)} {l.password && ( <> Password protected )} {l.visit_count > 0 && ( )} setQRModal(index)} /> setDeleteModal(index)} />
-1} closeHandler={() => setQRModal(-1)} > {links.items[qrModal] && ( )} -1} closeHandler={() => setDeleteModal(-1)} > {linkToDelete && ( <>

Delete link?

Are you sure do you want to delete the link{" "} "{removeProtocol(linkToDelete.link)}"? {deleteLoading ? ( <> ) : deleteMessage.text ? ( {deleteMessage.text} ) : ( <> )} )}
); }; export default LinksTable;