|
@@ -3,6 +3,7 @@ import { useRouter } from "next/router";
|
|
|
import { useQuery } from "@tanstack/react-query";
|
|
|
import dayjs from "dayjs";
|
|
|
import relativeTime from "dayjs/plugin/relativeTime";
|
|
|
+import toast from "react-hot-toast";
|
|
|
import {
|
|
|
AiOutlineEdit,
|
|
|
AiOutlineLock,
|
|
@@ -10,37 +11,29 @@ import {
|
|
|
AiOutlineUnlock,
|
|
|
} from "react-icons/ai";
|
|
|
import { Modal, ModalProps } from "src/components/Modal";
|
|
|
+import { Spinner } from "src/components/Spinner";
|
|
|
import { getAllJson, updateJson } from "src/services/db/json";
|
|
|
-import useUser from "src/store/useUser";
|
|
|
import styled from "styled-components";
|
|
|
|
|
|
dayjs.extend(relativeTime);
|
|
|
|
|
|
const StyledModalContent = styled.div`
|
|
|
display: flex;
|
|
|
- flex-wrap: wrap;
|
|
|
+ flex-direction: column;
|
|
|
gap: 14px;
|
|
|
overflow: auto;
|
|
|
`;
|
|
|
|
|
|
-const StyledJsonCard = styled.a`
|
|
|
+const StyledJsonCard = styled.a<{ active?: boolean }>`
|
|
|
display: block;
|
|
|
background: ${({ theme }) => theme.BLACK_SECONDARY};
|
|
|
- border: 2px solid ${({ theme }) => theme.BLACK_SECONDARY};
|
|
|
+ border: 2px solid ${({ theme, active }) => active ? theme.SEAGREEN : theme.BLACK_SECONDARY};
|
|
|
border-radius: 5px;
|
|
|
overflow: hidden;
|
|
|
- min-width: 200px;
|
|
|
- max-width: 250px;
|
|
|
flex: 1;
|
|
|
height: 160px;
|
|
|
`;
|
|
|
|
|
|
-const StyledImg = styled.img`
|
|
|
- width: 100%;
|
|
|
- height: 100px;
|
|
|
- object-fit: cover;
|
|
|
-`;
|
|
|
-
|
|
|
const StyledInfo = styled.div`
|
|
|
padding: 4px 6px;
|
|
|
`;
|
|
@@ -51,9 +44,10 @@ const StyledTitle = styled.div`
|
|
|
gap: 4px;
|
|
|
font-size: 14px;
|
|
|
font-weight: 500;
|
|
|
+ width: fit-content;
|
|
|
+ cursor: pointer;
|
|
|
|
|
|
span {
|
|
|
- max-width: 100%;
|
|
|
overflow: hidden;
|
|
|
text-overflow: ellipsis;
|
|
|
}
|
|
@@ -72,36 +66,63 @@ const StyledModal = styled(Modal)`
|
|
|
}
|
|
|
`;
|
|
|
|
|
|
-interface GraphCardProsp {
|
|
|
- id?: string;
|
|
|
- title: string;
|
|
|
- preview: string;
|
|
|
- details: string;
|
|
|
-}
|
|
|
+const StyledCreateWrapper = styled.div`
|
|
|
+ display: flex;
|
|
|
+ height: 100%;
|
|
|
+ gap: 6px;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ opacity: 0.6;
|
|
|
+ height: 45px;
|
|
|
+ font-size: 14px;
|
|
|
+ cursor: pointer;
|
|
|
+`;
|
|
|
|
|
|
-const GraphCard: React.FC<{ data: any }> = ({ data, ...props }) => {
|
|
|
+const StyledNameInput = styled.input`
|
|
|
+ background: transparent;
|
|
|
+ border: none;
|
|
|
+ outline: none;
|
|
|
+ width: 90%;
|
|
|
+ color: ${({ theme }) => theme.SEAGREEN};
|
|
|
+ font-weight: 600;
|
|
|
+`;
|
|
|
+
|
|
|
+const GraphCard: React.FC<{ data: any; refetch: () => void, active: boolean }> = ({
|
|
|
+ data,
|
|
|
+ refetch,
|
|
|
+ active,
|
|
|
+ ...props
|
|
|
+}) => {
|
|
|
const [editMode, setEditMode] = React.useState(false);
|
|
|
const [name, setName] = React.useState(data.name);
|
|
|
|
|
|
const onSubmit = () => {
|
|
|
- updateJson(data._id, { name });
|
|
|
+ toast
|
|
|
+ .promise(updateJson(data._id, { name }), {
|
|
|
+ loading: "Updating document...",
|
|
|
+ error: "Error occured while updating document!",
|
|
|
+ success: `Renamed document to ${name}`,
|
|
|
+ })
|
|
|
+ .then(refetch);
|
|
|
+
|
|
|
setEditMode(false);
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
- <StyledJsonCard href={`?json=${data._id}`} {...props}>
|
|
|
- <StyledImg
|
|
|
- width="200"
|
|
|
- height="100"
|
|
|
- src="https://blog.shevarezo.fr/uploads/posts/bulk/FNj3yQLp_visualiser-donnees-json-diagramme-json-crack_rotate3.png"
|
|
|
- />
|
|
|
+ <StyledJsonCard
|
|
|
+ href={`?json=${data._id}`}
|
|
|
+ as={editMode ? "div" : "a"}
|
|
|
+ active={active}
|
|
|
+ {...props}
|
|
|
+ >
|
|
|
<StyledInfo>
|
|
|
{editMode ? (
|
|
|
<form onSubmit={onSubmit}>
|
|
|
- <input
|
|
|
+ <StyledNameInput
|
|
|
value={name}
|
|
|
onChange={e => setName(e.currentTarget.value)}
|
|
|
onClick={e => e.preventDefault()}
|
|
|
+ autoFocus
|
|
|
/>
|
|
|
<input type="submit" hidden />
|
|
|
</form>
|
|
@@ -121,50 +142,46 @@ const GraphCard: React.FC<{ data: any }> = ({ data, ...props }) => {
|
|
|
{data.private ? <AiOutlineLock /> : <AiOutlineUnlock />}
|
|
|
Last modified {dayjs(data.updatedAt).fromNow()}
|
|
|
</StyledDetils>
|
|
|
- <StyledDetils></StyledDetils>
|
|
|
</StyledInfo>
|
|
|
</StyledJsonCard>
|
|
|
);
|
|
|
};
|
|
|
|
|
|
-const StyledCreateWrapper = styled.div`
|
|
|
- display: flex;
|
|
|
- height: 100%;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- opacity: 0.6;
|
|
|
- cursor: pointer;
|
|
|
-`;
|
|
|
-
|
|
|
const CreateCard: React.FC = () => (
|
|
|
<StyledJsonCard href="/editor">
|
|
|
<StyledCreateWrapper>
|
|
|
- <AiOutlinePlus size="30" />
|
|
|
+ <AiOutlinePlus size="24" />
|
|
|
+ Create New JSON
|
|
|
</StyledCreateWrapper>
|
|
|
</StyledJsonCard>
|
|
|
);
|
|
|
|
|
|
export const CloudModal: React.FC<ModalProps> = ({ visible, setVisible }) => {
|
|
|
const { isReady, query } = useRouter();
|
|
|
- const user = useUser(state => state.user);
|
|
|
- const { data, isLoading } = useQuery(
|
|
|
- ["allJson", query, user],
|
|
|
+
|
|
|
+ const { data, isFetching, refetch } = useQuery(
|
|
|
+ ["allJson", query],
|
|
|
() => getAllJson(),
|
|
|
{
|
|
|
enabled: isReady,
|
|
|
}
|
|
|
);
|
|
|
|
|
|
- if (isLoading) return <div>loading</div>;
|
|
|
return (
|
|
|
- <StyledModal size="lg" visible={visible} setVisible={setVisible}>
|
|
|
+ <StyledModal visible={visible} setVisible={setVisible}>
|
|
|
<Modal.Header>Saved On The Cloud</Modal.Header>
|
|
|
<Modal.Content>
|
|
|
<StyledModalContent>
|
|
|
- {data?.data?.result?.map(json => (
|
|
|
- <GraphCard data={json} key={json._id} />
|
|
|
- ))}
|
|
|
- <CreateCard />
|
|
|
+ {isFetching ? (
|
|
|
+ <Spinner />
|
|
|
+ ) : (
|
|
|
+ <>
|
|
|
+ <CreateCard />
|
|
|
+ {data?.data?.result?.map(json => (
|
|
|
+ <GraphCard data={json} key={json._id} refetch={refetch} active={query.json === json._id} />
|
|
|
+ ))}
|
|
|
+ </>
|
|
|
+ )}
|
|
|
</StyledModalContent>
|
|
|
</Modal.Content>
|
|
|
<Modal.Controls setVisible={setVisible}></Modal.Controls>
|