Final polish + cleaning
This commit is contained in:
parent
ba210c7c4e
commit
7b07f8a9dc
4
frontend/components/Editor/Link.module.css
Normal file
4
frontend/components/Editor/Link.module.css
Normal file
@ -0,0 +1,4 @@
|
||||
.input {
|
||||
width: 100%;
|
||||
padding-right: 16px;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import { Draggable } from "react-beautiful-dnd";
|
||||
import styles from "./Link.module.css";
|
||||
|
||||
export type EditableLink = {
|
||||
name: string;
|
||||
@ -56,6 +57,7 @@ const Link: React.FC<LinkProps> = ({ index, link, onChange, onDelete }) => {
|
||||
type="text"
|
||||
placeholder="Edit Title"
|
||||
value={link.name}
|
||||
className={styles.input}
|
||||
onChange={(e) => onChange({ ...link, name: e.target.value })}
|
||||
/>
|
||||
|
||||
@ -74,6 +76,7 @@ const Link: React.FC<LinkProps> = ({ index, link, onChange, onDelete }) => {
|
||||
type="url"
|
||||
placeholder="https://url"
|
||||
value={link.url}
|
||||
className={styles.input}
|
||||
onChange={(e) => onChange({ ...link, url: e.target.value })}
|
||||
/>
|
||||
|
||||
|
@ -15,26 +15,26 @@ interface EditorProps {
|
||||
const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
|
||||
const { displayDragDrop } = useDragDrop();
|
||||
const { headers } = useAuth();
|
||||
const [formState, setFormState] = useState<EditableLink[]>(links);
|
||||
const [editableLinks, setEditableLinks] = useState<EditableLink[]>(links);
|
||||
|
||||
useEffect(() => {
|
||||
setFormState(links);
|
||||
setEditableLinks(links);
|
||||
}, [links]);
|
||||
|
||||
const handleOnDragEnd = (result: DropResult) => {
|
||||
if (!result?.destination) return;
|
||||
|
||||
const items = Array.from(formState);
|
||||
const items = Array.from(editableLinks);
|
||||
const [reorderedItem] = items.splice(result.source.index, 1);
|
||||
items.splice(result.destination.index, 0, reorderedItem);
|
||||
|
||||
setFormState(items);
|
||||
setEditableLinks(items);
|
||||
};
|
||||
|
||||
/*note that we need to make the new links name render with nothing*/
|
||||
const handleOnClickAdd = () =>
|
||||
setFormState([
|
||||
...formState,
|
||||
setEditableLinks([
|
||||
...editableLinks,
|
||||
{
|
||||
name: "",
|
||||
url: "",
|
||||
@ -44,21 +44,20 @@ const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
|
||||
]);
|
||||
|
||||
const onSubmit = async () => {
|
||||
// const res = await updateLinks(formState);
|
||||
const res = await fetch("/api/editor/links", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...headers,
|
||||
},
|
||||
body: JSON.stringify({ links: formState }),
|
||||
body: JSON.stringify({ links: editableLinks }),
|
||||
});
|
||||
const updatedLinks = await res.json();
|
||||
setLinks(updatedLinks);
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
setFormState(links);
|
||||
setEditableLinks(links);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -80,22 +79,22 @@ const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
|
||||
{...provided.droppableProps}
|
||||
ref={provided.innerRef}
|
||||
>
|
||||
{formState.map((link, index) => (
|
||||
{editableLinks.map((link, index) => (
|
||||
<Link
|
||||
key={index}
|
||||
index={index}
|
||||
link={link}
|
||||
onChange={(newLink: EditableLink) =>
|
||||
setFormState([
|
||||
...formState.slice(0, index),
|
||||
setEditableLinks([
|
||||
...editableLinks.slice(0, index),
|
||||
newLink,
|
||||
...formState.slice(index + 1),
|
||||
...editableLinks.slice(index + 1),
|
||||
])
|
||||
}
|
||||
onDelete={() =>
|
||||
setFormState([
|
||||
...formState.slice(0, index),
|
||||
...formState.slice(index + 1),
|
||||
setEditableLinks([
|
||||
...editableLinks.slice(0, index),
|
||||
...editableLinks.slice(index + 1),
|
||||
])
|
||||
}
|
||||
/>
|
||||
@ -111,7 +110,7 @@ const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
|
||||
<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)}
|
||||
disabled={equal(editableLinks, links)}
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
@ -119,13 +118,13 @@ const Editor: React.FC<EditorProps> = ({ links, setLinks }) => {
|
||||
<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)}
|
||||
disabled={equal(editableLinks, links)}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<Preview links={formState} />
|
||||
<Preview links={editableLinks.filter((link) => link.active)} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,27 +1,30 @@
|
||||
import React, { ComponentPropsWithoutRef } from "react";
|
||||
import { Link } from "utils/types";
|
||||
import React from "react";
|
||||
|
||||
export interface Link {
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
interface LinkProps extends ComponentPropsWithoutRef<"div"> {
|
||||
interface Props {
|
||||
links: Link[];
|
||||
logClicks?: boolean;
|
||||
}
|
||||
|
||||
export const Links: React.FC<LinkProps> = ({ links, className }) => {
|
||||
const handleClick = (name: string, url: string) =>
|
||||
fetch("/api/clicks", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ name, url }),
|
||||
});
|
||||
export const Links: React.FC<Props> = ({ links, logClicks = false }) => {
|
||||
const handleClick = (name: string, url: string) => {
|
||||
if (logClicks) {
|
||||
fetch("/api/clicks", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ name, url }),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`text-s flex flex-col items-center w-full top-6 font-karla ${className}`}
|
||||
className={`text-s flex flex-col items-center w-full top-6 font-karla`}
|
||||
>
|
||||
<img className="mb-3" src="csc_logo.png" alt="CSC Logo" width="100px" />
|
||||
<h1 className="font-bold">@uwcsclub</h1>
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { Links } from "components/Links";
|
||||
import { Link, Links } from "components/Links";
|
||||
import React from "react";
|
||||
import styles from "./styles.module.css";
|
||||
|
||||
import { Link } from "utils/types";
|
||||
|
||||
interface PreviewProps {
|
||||
links: Link[];
|
||||
}
|
||||
@ -14,7 +12,9 @@ const Preview: React.FC<PreviewProps> = ({ links }) => {
|
||||
<div
|
||||
className={`box-border bg-white rounded-preview border-preview border-black ${styles.parent}`}
|
||||
>
|
||||
<Links links={links} className={styles.child} />
|
||||
<div className={styles.child}>
|
||||
<Links links={links} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"greeting": "Hello from JSON"
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
import React from "react";
|
||||
import { GetStaticProps } from "next";
|
||||
import GreetingJSON from "./hello-world.json";
|
||||
import { fetchExample } from "utils/api";
|
||||
|
||||
interface Props {
|
||||
greeting: string;
|
||||
}
|
||||
|
||||
export const getStaticProps: GetStaticProps<Props> = async () => {
|
||||
return {
|
||||
props: { greeting: GreetingJSON.greeting }, // will be passed to the page component as props
|
||||
// Next.js will attempt to re-generate the page:
|
||||
// - When a request comes in
|
||||
// - At most once every second
|
||||
revalidate: 1,
|
||||
};
|
||||
};
|
||||
|
||||
function HelloWorld({ greeting }: Props): JSX.Element {
|
||||
const [greetings, setGreetings] = React.useState([greeting]);
|
||||
|
||||
const getMoreGreetings = async () => {
|
||||
const greetingFromBackend = await fetchExample();
|
||||
setGreetings([
|
||||
...greetings,
|
||||
`"${greetingFromBackend}" --- ${new Date().toISOString()}`,
|
||||
]);
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ padding: "50px" }}>
|
||||
<button
|
||||
style={{ border: "2px solid black", padding: "5px" }}
|
||||
onClick={getMoreGreetings}
|
||||
>
|
||||
Get greeting from the server
|
||||
</button>
|
||||
<ol style={{ listStyleType: "decimal" }}>
|
||||
{greetings.map((greeting) => (
|
||||
<li key={greeting}>{greeting}</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default HelloWorld;
|
@ -17,7 +17,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const Home: React.FC<Props> = ({ links }) => {
|
||||
return <Links links={links} />;
|
||||
return <Links links={links} logClicks={true} />;
|
||||
};
|
||||
|
||||
export default Home;
|
||||
|
@ -1,4 +0,0 @@
|
||||
export async function fetchExample(): Promise<string> {
|
||||
const response = await fetch("/api");
|
||||
return await response.text();
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
export interface Link {
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user