diff --git a/src/assets/github.png b/src/assets/github.png new file mode 100644 index 0000000..a3a73d6 Binary files /dev/null and b/src/assets/github.png differ diff --git a/src/assets/google.png b/src/assets/google.png new file mode 100644 index 0000000..fa72a27 Binary files /dev/null and b/src/assets/google.png differ diff --git a/src/components/table.jsx b/src/components/table.jsx index b21e95a..8c8bd45 100644 --- a/src/components/table.jsx +++ b/src/components/table.jsx @@ -100,9 +100,9 @@ export default function Table(props) { ? props.tableData.name.length < 10 ? props.tableData.name : `${props.tableData.name.substring(0, 10)}...` - : props.tableData.name.length < 14 + : props.tableData.name.length < 16 ? props.tableData.name - : `${props.tableData.name.substring(0, 14)}...`} + : `${props.tableData.name.substring(0, 16)}...`} {isHovered && (
diff --git a/src/pages/signup.jsx b/src/pages/signup.jsx index 402eec2..650ed00 100644 --- a/src/pages/signup.jsx +++ b/src/pages/signup.jsx @@ -1,20 +1,335 @@ -import { useEffect, useState } from "react"; +import { useEffect, useState, useRef } from "react"; import { Link } from "react-router-dom"; -import logo from "../assets/logo_light_46.png"; -import ReCAPTCHA from "react-google-recaptcha"; -import { IconEyeClosedSolid, IconEyeOpened } from "@douyinfe/semi-icons"; -import { Banner } from "@douyinfe/semi-ui"; +import logo from "../assets/icon_dark_64.png"; +import google_logo from "../assets/google.png"; +import github_logo from "../assets/github.png"; import axios from "axios"; +import { Cardinality } from "../data/data"; +import { calcPath } from "../utils"; +import { Toast } from "@douyinfe/semi-ui"; + +const xOffset = window.innerWidth * 0.42 * 0.15; +const diagram = { + tables: [ + { + name: "galactic_users", + x: xOffset + 101, + y: window.innerHeight * 0.75 - (4 * 36 + 50 + 7) * 0.5, + fields: [ + { + name: "id", + type: "INT", + }, + { + name: "username", + type: "VARCHAR", + }, + { + name: "email", + type: "VARCHAR", + }, + { + name: "password", + type: "VARCHAR", + }, + ], + color: "#7d9dff", + }, + { + name: "celestial_data", + x: xOffset, + y: window.innerHeight * 0.32 - (5 * 36 + 50 + 7) * 0.5, + fields: [ + { + name: "id", + type: "INT", + }, + { + name: "user_id", + type: "INT", + }, + { + name: "type", + type: "ENUM", + }, + { + name: "time", + type: "TIMESTAMP", + }, + { + name: "content", + type: "VARCHAR", + }, + ], + color: "#89e667", + }, + ], + relationships: [ + { + startTableId: 1, + startFieldId: 1, + endTableId: 0, + endFieldId: 0, + startX: xOffset + 16, + startY: + window.innerHeight * 0.32 - (4 * 36 + 50 + 7) * 0.5 + (50 + 18 * 2), + endX: xOffset + 115, + endY: window.innerHeight * 0.75 - (4 * 36 + 50 + 7) * 0.5 + (50 + 18 * 1), + cardinality: "One to one", + }, + ], +}; + +function Table({ table, grab }) { + const [isHovered, setIsHovered] = useState(false); + const [hoveredField, setHoveredField] = useState(-1); + const height = table.fields.length * 36 + 50 + 7; + return ( + setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + > +
+
+
+ {table.name} +
+ {table.fields.map((e, i) => ( +
setHoveredField(i)} + onMouseLeave={() => setHoveredField(-1)} + > +
+
+
{e.type}
+
+ ))} +
+ + ); +} + +function Relationship({ relationship }) { + const pathRef = useRef(); + let start = { x: 0, y: 0 }; + let end = { x: 0, y: 0 }; + + let cardinalityStart = "1"; + let cardinalityEnd = "1"; + + switch (relationship.cardinality) { + case Cardinality.MANY_TO_ONE: + cardinalityStart = "n"; + cardinalityEnd = "1"; + break; + case Cardinality.ONE_TO_MANY: + cardinalityStart = "1"; + cardinalityEnd = "n"; + break; + case Cardinality.ONE_TO_ONE: + cardinalityStart = "1"; + cardinalityEnd = "1"; + break; + default: + break; + } + + const length = 32; + + const [refAquired, setRefAquired] = useState(false); + useEffect(() => { + setRefAquired(true); + }, []); + + if (refAquired) { + const pathLength = pathRef.current.getTotalLength(); + const point1 = pathRef.current.getPointAtLength(length); + start = { x: point1.x, y: point1.y }; + const point2 = pathRef.current.getPointAtLength(pathLength - length); + end = { x: point2.x, y: point2.y }; + } + + return ( + console.log(pathRef.current)}> + + {pathRef.current && ( + <> + + + {cardinalityStart} + + + + {cardinalityEnd} + + + )} + + ); +} + +function Canvas() { + const [tables, setTables] = useState(diagram.tables); + const [relationships, setRelationships] = useState(diagram.relationships); + const [dragging, setDragging] = useState(-1); + const [offset, setOffset] = useState({ x: 0, y: 0 }); + + const grabTable = (e, id) => { + setDragging(id); + setOffset({ + x: e.clientX - tables[id].x, + y: e.clientY - tables[id].y, + }); + }; + + const moveTable = (e) => { + if (dragging !== -1) { + const dx = e.clientX - offset.x; + const dy = e.clientY - offset.y; + setTables((prev) => + prev.map((table, i) => { + if (i === dragging) { + setRelationships((prev) => + prev.map((r) => { + if (r.startTableId === i) { + return { + ...r, + startX: dx + 15, + startY: dy + r.startFieldId * 36 + 69, + endX: tables[r.endTableId].x + 15, + endY: tables[r.endTableId].y + r.endFieldId * 36 + 69, + }; + } else if (r.endTableId === i) { + return { + ...r, + startX: tables[r.startTableId].x + 15, + startY: tables[r.startTableId].y + r.startFieldId * 36 + 69, + endX: dx + 15, + endY: dy + r.endFieldId * 36 + 69, + }; + } + return r; + }) + ); + + return { + ...table, + x: dx, + y: dy, + }; + } + return table; + }) + ); + } + }; + + const releaseTable = () => { + setDragging(-1); + setOffset({ x: 0, y: 0 }); + }; + + return ( + + + + + + + + {tables.map((t, i) => ( + grabTable(e, i)} /> + ))} + {relationships.map((r, i) => ( + + ))} + + ); +} export default function SignUp() { const [formValues, setFormValues] = useState({ - captcha: false, username: "", email: "", password: "", }); const [showPassword, setShowPassword] = useState(false); - const [showPassCriteria, setShowPassCriteria] = useState(false); + const [showVerified, setShowVerified] = useState(false); + const [resendCounter, setResendCounter] = useState(0); const handleChange = (e) => setFormValues((prev) => ({ @@ -29,134 +344,170 @@ export default function SignUp() { email: formValues.email, password: formValues.password, }) - .then((res) => { - console.log(res); - }) + .then(() => setShowVerified(true)) .catch(() => {}); }; + const resendEmail = async () => { + await axios + .post(`${import.meta.env.VITE_API_BACKEND_URL}/resend`, { + username: formValues.username, + email: formValues.email, + password: formValues.password, + }) + .then(() => setResendCounter((prev) => prev + 1)) + .catch((e) => { + if (e.response.status === 400) + Toast.error("Account has already been verified."); + }); + }; + useEffect(() => { document.title = "Create account | drawDB"; }); return ( -
-
-
+
+
+ - logo + -
- Create your account today! -
-
- - - - - -
- setShowPassCriteria(true)} - onChange={handleChange} - /> - -
- {showPassCriteria && ( - - Password isn't secure +
+
+
+ {!showVerified ? ( + <> +
+ Create Account +
+
+ + +
+
+
+
or
+
+
+
+ + + + + +
+ +
- } - description={ -
-
    -
  • Contain at least 8 characters
  • -
  • Contain a special character
  • -
  • Contain a number
  • -
+ +
+ Already have an account? + + Log in here. +
- } - closeIcon={null} - > +
+ + ) : ( + <> +
+ Verify Account +
+
+
+ We {resendCounter == 0 ? "sent" : "resent"} a verification + email to{" "} + + {formValues.email} + + . +
+
Please check your inbox and verify your email.
+
+
+
Don't see the email?
+ {resendCounter < 4 ? ( +
+ If you haven't recieved the email after a few minutes, + make sure to check your junk mail or{" "} + + . +
+ ) : ( +
+ Looks like we're having trouble signing you up. Please + try again in a little bit or contact us at{" "} + + drawdb@gmail.com + +
+ )} +
+ )} - - setFormValues((prev) => ({ ...prev, captcha: true })) - } - /> - -
- Already have an account? - - Log in here. - -
-
-
-
or
-
-
- -
diff --git a/src/utils/index.js b/src/utils/index.js index 5c88750..8a152ce 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -624,13 +624,9 @@ const calcPath = (x1, x2, y1, y2, startFieldId, endFieldId, zoom = 1) => { r = Math.abs(y2 - y1) / 3; if (r <= 2) { if (x1 + tableWidth <= x2) - return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${x2 + 0.1} ${ - y2 + 0.1 - }`; + return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${x2} ${y2 + 0.1}`; else if (x2 + tableWidth < x1) - return `M ${x2 + tableWidth - 2 * offsetX} ${y2} L ${x1 + 0.1} ${ - y1 + 0.1 - }`; + return `M ${x2 + tableWidth - 2 * offsetX} ${y2} L ${x1} ${y1 + 0.1}`; } } diff --git a/tailwind.config.js b/tailwind.config.js index 747ef68..619a0f9 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -9,7 +9,7 @@ export default { '2xl': {'max': '1535px'}, 'xl': {'min': '1024px'}, 'lg': {'max': '1023px'}, - 'md': {'max': '767px'}, + 'md': {'max': '820px'}, 'sm': {'max': '639px'} }, extend: {}