Hookup preview component

This commit is contained in:
Steven Xu 2021-04-04 11:35:14 -04:00
parent 413a00259c
commit ba210c7c4e
9 changed files with 571 additions and 498 deletions

View File

@ -1,43 +0,0 @@
import React from "react";
const Question = (
<svg
xmlnsXlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
color="#000"
viewBox="0 0 16 16"
className="sc-dkIXFM jmmNux"
width="14"
height="14"
>
<path d="M8 0a8 8 0 108 8 8 8 0 00-8-8zm0 15a7 7 0 117-7 7 7 0 01-7 7zm-.75-3.49h1.53V13H7.25zm3.54-7A3.05 3.05 0 0111 5.72a2.54 2.54 0 01-.1.76 2.9 2.9 0 01-.27.62 3.75 3.75 0 01-.38.51l-.44.45-.43.42a5.58 5.58 0 00-.38.46 2.33 2.33 0 00-.27.52 1.83 1.83 0 00-.11.64v.54H7.44V10a2.57 2.57 0 01.22-1 3 3 0 01.45-.73 6.25 6.25 0 01.57-.58 7.4 7.4 0 00.55-.57 2.42 2.42 0 00.4-.65 1.82 1.82 0 00.13-.87 1.81 1.81 0 00-.49-1.19A1.63 1.63 0 008.09 4a1.91 1.91 0 00-.86.18 1.74 1.74 0 00-.59.49 1.91 1.91 0 00-.36.71 3.7 3.7 0 00-.11.9H5A3.71 3.71 0 015.2 5a3.17 3.17 0 01.61-1.1 2.85 2.85 0 011-.69A3.21 3.21 0 018.09 3a3.4 3.4 0 011.18.19 2.71 2.71 0 01.92.53 2.6 2.6 0 01.6.83z"></path>
</svg>
);
const Chevron = (
<svg
xmlnsXlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 12 12"
className="sc-hHftDr bphBpT"
rotate="0"
data-test="IconComponent"
width="16"
height="20"
>
<rect
rotate="0"
data-test="IconComponent"
className="sc-fKFyDc gYoavR"
fillOpacity="0"
fill="#000000"
></rect>
<polygon
transform="translate(5.949747, 4.949747) rotate(-45.000000) translate(-5.949747, -4.949747) "
points="4.44974747 6.44974747 4.44974747 1.44974747 2.44974747 1.44974747 2.44974747 8.44974747 9.44974747 8.44974747 9.44974747 6.44974747"
fill="#0A0B0D"
></polygon>
</svg>
);
export { Question, Chevron };

View File

@ -1,6 +1,30 @@
import React from "react"; import React from "react";
import { Question, Chevron } from "./assets";
const Chevron = () => (
<svg
xmlnsXlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 12 12"
className="sc-hHftDr bphBpT"
rotate="0"
data-test="IconComponent"
width="16"
height="20"
>
<rect
rotate="0"
data-test="IconComponent"
className="sc-fKFyDc gYoavR"
fillOpacity="0"
fill="#000000"
/>
<polygon
transform="translate(5.949747, 4.949747) rotate(-45.000000) translate(-5.949747, -4.949747) "
points="4.44974747 6.44974747 4.44974747 1.44974747 2.44974747 1.44974747 2.44974747 8.44974747 9.44974747 8.44974747 9.44974747 6.44974747"
fill="#0A0B0D"
/>
</svg>
);
interface AnalyticsProps { interface AnalyticsProps {
clicks: number; clicks: number;
} }
@ -17,10 +41,9 @@ const Analytics: React.FC<AnalyticsProps> = ({ clicks }) => {
<p className="font-bold lt-lg:font-normal">{clicks || "-"}</p> <p className="font-bold lt-lg:font-normal">{clicks || "-"}</p>
</div> </div>
</div> </div>
<div>{Question}</div>
</div> </div>
<div className="w-full h-full flex-chevron flex flex-row justify-center items-center"> <div className="w-full h-full flex-chevron flex flex-row justify-center items-center">
{Chevron} <Chevron />
</div> </div>
</div> </div>
); );

View File

@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react";
import { DragDropContext, Droppable, DropResult } from "react-beautiful-dnd"; import { DragDropContext, Droppable, DropResult } from "react-beautiful-dnd";
import Link, { EditableLink } from "components/Editor/Link"; import Link, { EditableLink } from "components/Editor/Link";
import { useAuth } from "components/Login/AuthContext"; import { useAuth } from "components/Login/AuthContext";
import Preview from "components/Preview";
import { useDragDrop } from "./useDragDrop"; import { useDragDrop } from "./useDragDrop";
import equal from "fast-deep-equal"; import equal from "fast-deep-equal";
@ -12,9 +13,9 @@ interface EditorProps {
} }
const Editor: React.FC<EditorProps> = ({ links, setLinks }) => { const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
const [formState, setFormState] = useState<EditableLink[]>(links);
const { displayDragDrop } = useDragDrop(); const { displayDragDrop } = useDragDrop();
const { headers } = useAuth(); const { headers } = useAuth();
const [formState, setFormState] = useState<EditableLink[]>(links);
useEffect(() => { useEffect(() => {
setFormState(links); setFormState(links);
@ -42,10 +43,6 @@ const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
}, },
]); ]);
useEffect(() => {
setFormState(links);
}, [links]);
const onSubmit = async () => { const onSubmit = async () => {
// const res = await updateLinks(formState); // const res = await updateLinks(formState);
const res = await fetch("/api/editor/links", { const res = await fetch("/api/editor/links", {
@ -65,67 +62,70 @@ const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
}; };
return ( return (
<div className="space-y-4 bg-gray-100 w-1/2 p-2"> <div className="flex">
{/* add link button */} <div className="space-y-4 bg-gray-100 w-1/2 p-2">
<button {/* add link button */}
className="block flex py-2 items-center justify-center rounded-md bg-purple-600 hover:bg-purple-500 cursor-pointer text-white w-full"
onClick={handleOnClickAdd}
>
Add New Link
</button>
{displayDragDrop && (
<DragDropContext onDragEnd={handleOnDragEnd}>
<Droppable droppableId="links">
{(provided) => (
<div
className="links"
{...provided.droppableProps}
ref={provided.innerRef}
>
{formState.map((link, index) => (
<Link
key={index}
index={index}
link={link}
onChange={(newLink: EditableLink) =>
setFormState([
...formState.slice(0, index),
newLink,
...formState.slice(index + 1),
])
}
onDelete={() =>
setFormState([
...formState.slice(0, index),
...formState.slice(index + 1),
])
}
/>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
)}
<div className="mb-16" />
<div className="flex">
<button <button
className="block flex py-2 items-center justify-center rounded-md bg-purple-600 hover:bg-purple-500 cursor-pointer text-white w-full disabled:opacity-50" className="block flex py-2 items-center justify-center rounded-md bg-purple-600 hover:bg-purple-500 cursor-pointer text-white w-full"
onClick={onSubmit} onClick={handleOnClickAdd}
disabled={equal(formState, links)}
> >
Submit Add New Link
</button>
<div className="mr-4" />
<button
className="block flex py-2 items-center justify-center rounded-md bg-purple-600 hover:bg-purple-500 cursor-pointer text-white w-full disabled:opacity-50"
onClick={onCancel}
disabled={equal(formState, links)}
>
Cancel
</button> </button>
{displayDragDrop && (
<DragDropContext onDragEnd={handleOnDragEnd}>
<Droppable droppableId="links">
{(provided) => (
<div
className="links"
{...provided.droppableProps}
ref={provided.innerRef}
>
{formState.map((link, index) => (
<Link
key={index}
index={index}
link={link}
onChange={(newLink: EditableLink) =>
setFormState([
...formState.slice(0, index),
newLink,
...formState.slice(index + 1),
])
}
onDelete={() =>
setFormState([
...formState.slice(0, index),
...formState.slice(index + 1),
])
}
/>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
)}
<div className="mb-16" />
<div className="flex">
<button
className="block flex py-2 items-center justify-center rounded-md bg-purple-600 hover:bg-purple-500 cursor-pointer text-white w-full disabled:opacity-50"
onClick={onSubmit}
disabled={equal(formState, links)}
>
Submit
</button>
<div className="mr-4" />
<button
className="block flex py-2 items-center justify-center rounded-md bg-purple-600 hover:bg-purple-500 cursor-pointer text-white w-full disabled:opacity-50"
onClick={onCancel}
disabled={equal(formState, links)}
>
Cancel
</button>
</div>
</div> </div>
<Preview links={formState} />
</div> </div>
); );
}; };

View File

@ -1,27 +1,15 @@
import React from "react"; import React, { ComponentPropsWithoutRef } from "react";
import { Link } from "utils/types";
export interface Link { export interface Link {
name: string; name: string;
url: string; url: string;
} }
interface LinkProps { interface LinkProps extends ComponentPropsWithoutRef<"div"> {
links: Link[]; links: Link[];
} }
export const Links: React.FC<LinkProps> = ({ links }) => { export const Links: React.FC<LinkProps> = ({ links, className }) => {
const postData = (url = ""): void => {
fetch(url, {
method: "POST",
})
.then((response) => response.json())
.then((data) => {
console.log("Success:", data);
})
.catch((error) => {
console.error("Error:", error);
});
};
const handleClick = (name: string, url: string) => const handleClick = (name: string, url: string) =>
fetch("/api/clicks", { fetch("/api/clicks", {
method: "POST", method: "POST",
@ -32,7 +20,9 @@ export const Links: React.FC<LinkProps> = ({ links }) => {
}); });
return ( return (
<div className="text-s flex flex-col items-center w-full absolute top-6 font-karla"> <div
className={`text-s flex flex-col items-center w-full top-6 font-karla ${className}`}
>
<img className="mb-3" src="csc_logo.png" alt="CSC Logo" width="100px" /> <img className="mb-3" src="csc_logo.png" alt="CSC Logo" width="100px" />
<h1 className="font-bold">@uwcsclub</h1> <h1 className="font-bold">@uwcsclub</h1>
<ul className="flex flex-col my-6 w-full"> <ul className="flex flex-col my-6 w-full">

View File

@ -1,7 +1,23 @@
import { Links } from "components/Links";
import React from "react"; import React from "react";
import styles from "./styles.module.css";
const Preview: React.FC = () => { import { Link } from "utils/types";
return <div />;
interface PreviewProps {
links: Link[];
}
const Preview: React.FC<PreviewProps> = ({ links }) => {
return (
<div className={styles.container}>
<div
className={`box-border bg-white rounded-preview border-preview border-black ${styles.parent}`}
>
<Links links={links} className={styles.child} />
</div>
</div>
);
}; };
export default Preview; export default Preview;

View File

@ -0,0 +1,14 @@
.parent {
width: 300px;
height: 600px;
overflow: hidden;
}
.child {
width: 100%;
height: 100%;
overflow-y: scroll;
padding-right: 17px; /* Increase/decrease this value for cross-browser compatibility */
padding-left: 5px;
box-sizing: content-box; /* So the width will be 100% + 17px */
}

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,9 @@ module.exports = {
}, },
darkMode: false, // or 'media' or 'class' darkMode: false, // or 'media' or 'class'
theme: { theme: {
fontFamily: {
body: ["Karla", "sans-serif"],
},
extend: { extend: {
colors: { colors: {
analytics: { analytics: {
@ -38,6 +41,12 @@ module.exports = {
analytics: "1 0 0", analytics: "1 0 0",
chevron: "0 0 16px", chevron: "0 0 16px",
}, },
borderRadius: {
preview: "3.2rem",
},
borderWidth: {
preview: "0.75rem",
},
}, },
container: { container: {
center: true, center: true,
@ -48,5 +57,4 @@ module.exports = {
opacity: ["disabled"], opacity: ["disabled"],
}, },
}, },
plugins: [],
}; };

4
frontend/utils/types.ts Normal file
View File

@ -0,0 +1,4 @@
export interface Link {
name: string;
url: string;
}