diff --git a/package.json b/package.json
index 7f6d4a8..f698cd2 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"localstoragedb": "^2.3.2",
"react": "^16.12.0",
"react-dom": "^16.12.0",
+ "react-icons": "^3.11.0",
"react-router-dom": "^5.1.2",
"react-scripts": "3.2.0"
},
@@ -33,5 +34,8 @@
"last 1 firefox version",
"last 1 safari version"
]
+ },
+ "devDependencies": {
+ "prettier": "^2.1.2"
}
}
diff --git a/src/App.js b/src/App.js
index 57ef9cf..9da5da3 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,10 +1,43 @@
-import React from "react"
-import { BrowserRouter as Router, Switch, Route } from "react-router-dom"
-import { ThemeProvider, theme, CSSReset } from "@chakra-ui/core"
-import LoginWrapper from "./auth/LoginWrapper"
-import LogoutPage from "./auth/LogoutPage"
-import Frame from "./ui/Frame"
-import Home from "./Home"
+import React from "react";
+import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
+import { ThemeProvider, theme, CSSReset } from "@chakra-ui/core";
+import LoginWrapper from "./auth/LoginWrapper";
+import LogoutPage from "./auth/LogoutPage";
+import Frame from "./ui/Frame";
+import Settings from "./pages/Settings";
+import Founders from "./pages/Founders";
+
+const OnboardingApp = ({ username, logout }) => (
+
+
+
+
+
+
+
+
+
+
+);
+
+const OnboardedApp = ({ username, logout }) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
function App() {
return (
@@ -12,22 +45,17 @@ function App() {
- {({ username, logout }) => (
-
-
-
-
-
-
-
-
-
-
- )}
+ {({ username, logout, onboarded }) =>
+ onboarded ? (
+
+ ) : (
+
+ )
+ }
- )
+ );
}
-export default App
+export default App;
diff --git a/src/Home.js b/src/Home.js
deleted file mode 100644
index 0a2d19e..0000000
--- a/src/Home.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import React from 'react'
-import Card from './ui/Card'
-import DataAccessDemo from './features/DemoDataAccess'
-
-const Home = ({username}) => {
- return
-
-
-}
-
-export default Home
-
-
-
-
\ No newline at end of file
diff --git a/src/auth/LoginWrapper.js b/src/auth/LoginWrapper.js
index c5d5f40..2ad289e 100644
--- a/src/auth/LoginWrapper.js
+++ b/src/auth/LoginWrapper.js
@@ -1,4 +1,4 @@
-import React from "react"
+import React from "react";
import {
Box,
Flex,
@@ -7,29 +7,37 @@ import {
Button,
FormControl,
FormLabel,
- FormHelperText
-} from "@chakra-ui/core"
-import Header from "../ui/Header"
+ FormHelperText,
+} from "@chakra-ui/core";
+import Header from "../ui/Header";
+import db from "../data/database";
export default class LoginWrapper extends React.Component {
- state = { username: localStorage.getItem("username") || null }
+ state = {
+ username: localStorage.getItem("username") || null,
+ };
- login = username => {
- localStorage.setItem("username", username)
- this.setState({ username: username })
- }
+ login = (username) => {
+ localStorage.setItem("username", username);
+ this.setState({ username: username });
+ };
logout = () => {
- localStorage.removeItem("username")
- this.setState({ username: undefined })
- }
+ localStorage.removeItem("username");
+ this.setState({ username: undefined });
+ };
render() {
- let { username } = this.state
- let inputRef = React.createRef()
+ let { username } = this.state;
+ let inputRef = React.createRef();
// If we are logged in, then pass the username to the children.
if (username) {
- return this.props.children({ username, logout: this.logout })
+ const results = db.queryAll("founders", { query: { username } });
+ return this.props.children({
+ username,
+ logout: this.logout,
+ onboarded: results.length > 0,
+ });
}
// Otherwise, show a login form.
@@ -39,7 +47,6 @@ export default class LoginWrapper extends React.Component {
- Username
-
-
- Your email, or literally anything
-
+ Username
+
+ Your email, or literally anything
- )
+ );
}
}
diff --git a/src/data/database.js b/src/data/database.js
index ca9fc36..9af60ea 100644
--- a/src/data/database.js
+++ b/src/data/database.js
@@ -1,30 +1,125 @@
-import localStorageDB from "localstoragedb"
+import localStorageDB from "localstoragedb";
// Uses https://github.com/knadh/localStorageDB
// Initialise. If the database doesn't exist, it is created
////////////////////////////////////////////////
-// Change the dbName if you change the schema or
+// Change the dbName if you change the schema or
// initial data to reset the db
-const dbName = "userData_2"
+const dbName = "userDatabase";
/////////////////////////////////////////////////
var db = new localStorageDB(dbName, localStorage);
// Check if the database was just created. Useful for initial database setup
-if( !db.tableExists("posts")) {
- // create the "posts" table
- db.createTable("posts", ["user", "title"]);
+const addFounder = (
+ username,
+ firstName,
+ lastName,
+ location,
+ introduction,
+ contact,
+ skills,
+ cofounderSkills
+) =>
+ db.insert("founders", {
+ username,
+ firstName,
+ lastName,
+ location,
+ introduction,
+ contact,
+ skills,
+ cofounderSkills,
+ });
- // insert some data
- db.insert("posts", {user: "billgates", title: "Microsoft is great"});
- db.insert("posts", {user: "billgates", title: "It looks like you're writing a letter"});
- db.insert("posts", {user: "stevejobs", title: "It just works"});
+if (!db.tableExists("matches")) {
+ db.createTable("matches", ["username", "invitedUsername", "status"]);
+}
+
+if (!db.tableExists("founders")) {
+ db.createTable("founders", [
+ "username",
+ "firstName",
+ "lastName",
+ "location",
+ "introduction",
+ "contact",
+ "skills",
+ "cofounderSkills",
+ ]);
+
+ addFounder(
+ "jmar",
+ "Jim",
+ "Marino",
+ "Washington",
+ "Co-founder of Tuft & Needle (T&N) and Chief Strategy Officer of Serta Simmons Bedding, Jim Marino is a passionate storyteller, facilitator and teacher, inspiring T&N's most challenging and disruptive projects. Pioneering the disruption of the mattress industry space from brick and mortar to e-commerce, JT is now leading the charge in reinventing retail as we know it to create a true omni-channel “clicks to bricks” experience for consumers. The brand is widely known for iterating, and JT is at the helm of this retail evolution.",
+ "twitter: @jmar",
+ [
+ { name: "Marketing", rank: 2 },
+ { name: "Leadership", rank: 4 },
+ { name: "Fundraising", rank: 2 },
+ { name: "Engineering", rank: 5 },
+ { name: "Sales", rank: 2 },
+ ],
+ [
+ { name: "Marketing", rank: 5 },
+ { name: "Leadership", rank: 2 },
+ { name: "Fundraising", rank: 1 },
+ { name: "Engineering", rank: 5 },
+ { name: "Sales", rank: 5 },
+ ]
+ );
+ addFounder(
+ "jrob",
+ "John",
+ "Robertson",
+ "LA",
+ "John is also the Co-Founder and Vice-Chairman of Human Longevity Inc. (HLI), a genomics and cell therapy-based diagnostic and therapeutic company focused on extending the healthy human lifespan. He is also the Co-Founder and Executive Chairman of Singularity University, a graduate-level Silicon Valley institution that studies exponentially growing technologies, their ability to transform industries and solve humanity’s grand challenges.",
+ "twitter: @jrob",
+ [
+ { name: "Marketing", rank: 5 },
+ { name: "Leadership", rank: 2 },
+ { name: "Fundraising", rank: 1 },
+ { name: "Engineering", rank: 5 },
+ { name: "Sales", rank: 5 },
+ ],
+ [
+ { name: "Marketing", rank: 5 },
+ { name: "Leadership", rank: 2 },
+ { name: "Fundraising", rank: 1 },
+ { name: "Engineering", rank: 5 },
+ { name: "Sales", rank: 5 },
+ ]
+ );
+ addFounder(
+ "daep",
+ "Daehee",
+ "Park",
+ "New York",
+ "Daehee Park is the co-founder of Tuft & Needle (T&N), a digitally-native sleep brand that offers high quality products for the bedroom at a fair price while providing an award-winning customer experience. There, he leads business and marketing strategy and has been instrumental in redefining the sleep industry and retail experience through the businesses’ rapid nationwide retail expansion, award-winning company culture, evolving product offering and acclaimed advertising campaigns.",
+ "twitter: @daep",
+ [
+ { name: "Marketing", rank: 1 },
+ { name: "Leadership", rank: 1 },
+ { name: "Fundraising", rank: 5 },
+ { name: "Engineering", rank: 5 },
+ { name: "Sales", rank: 2 },
+ ],
+ [
+ { name: "Marketing", rank: 5 },
+ { name: "Leadership", rank: 1 },
+ { name: "Fundraising", rank: 4 },
+ { name: "Engineering", rank: 1 },
+ { name: "Sales", rank: 3 },
+ ]
+ );
- // commit the database to localStorage
- // all create/drop/insert/update/delete operations should be committed
- db.commit();
+ // commit the database to localStorage
+ // all create/drop/insert/update/delete operations should be committed
+ db.commit();
}
-export default db
\ No newline at end of file
+export default db;
diff --git a/src/pages/Founders.js b/src/pages/Founders.js
new file mode 100644
index 0000000..fdb92fe
--- /dev/null
+++ b/src/pages/Founders.js
@@ -0,0 +1,79 @@
+import React, { useState } from "react";
+import { SimpleGrid, Heading } from "@chakra-ui/core";
+import db from "../data/database";
+import Card from "../ui/Card";
+
+export default ({ username, completed }) => {
+ const [founders, setFounders] = useState(
+ db.queryAll("founders", {
+ query: (row) => row.username !== username,
+ })
+ );
+
+ const sendInvitation = (founder) => {
+ const [match] = db.queryAll("matches", {
+ query: { username: founder, invitedUsername: username },
+ limit: 1,
+ });
+
+ if (match) {
+ // connection already exist, time to match both parties
+ db.insertOrUpdate(
+ "matches",
+ { username: founder, invitedUsername: username },
+ { username: founder, invitedUsername: username, status: "completed" }
+ );
+ db.insertOrUpdate(
+ "matches",
+ { username: username, invitedUsername: founder },
+ { username: username, invitedUsername: founder, status: "completed" }
+ );
+ } else {
+ // send one way invitation
+ db.insertOrUpdate(
+ "matches",
+ { username, invitedUsername: founder },
+ { username, invitedUsername: founder, status: "invited" }
+ );
+ }
+ db.commit();
+ setFounders(
+ founders.map((element) =>
+ element.username === founder.username
+ ? { ...element, matchStatus: "pending" }
+ : element
+ )
+ );
+ };
+
+ const renderPosts = () => {
+ const invitations = db.queryAll("matches", { query: { username } });
+ const results = founders
+ .map((founder) => ({
+ ...founder,
+ matchStatus:
+ invitations.find(
+ (invitation) => invitation.invitedUsername === founder.username
+ )?.status || "new",
+ }))
+ .filter((founder) =>
+ completed ? founder.matchStatus === "completed" : true
+ );
+ if (!results.length) return No founders found :(;
+ return results.map((founder, index) => (
+
+ ));
+ };
+
+ return (
+
+ {renderPosts()}
+
+ );
+};
diff --git a/src/pages/Settings.js b/src/pages/Settings.js
new file mode 100644
index 0000000..de163f1
--- /dev/null
+++ b/src/pages/Settings.js
@@ -0,0 +1,161 @@
+import React, { useState } from "react";
+import {
+ Alert,
+ Box,
+ Button,
+ FormControl,
+ FormLabel,
+ Heading,
+ Input,
+ Stack,
+ Textarea,
+} from "@chakra-ui/core";
+import db from "../data/database";
+import SkillBox from "../ui/SkillBox";
+
+const skills = [
+ "Marketing",
+ "Leadership",
+ "Fundraising",
+ "Engineering",
+ "Sales",
+];
+const generateSkillMap = () => skills.map((name) => ({ name, rank: 1 }));
+
+const Settings = ({ username, onboarding = false }) => {
+ const [user] = db.queryAll("founders", { query: { username }, limit: 1 });
+
+ const [firstName, setFirstName] = useState(user?.firstName || "");
+ const [lastName, setLastName] = useState(user?.lastName || "");
+ const [location, setLocation] = useState(user?.location || "");
+ const [contact, setContact] = useState(user?.contact || "");
+
+ const [introduction, setIntroduction] = useState(user?.introduction || "");
+
+ const [mySkills, setMySkills] = useState(user?.skills || generateSkillMap());
+ const [cofounderSkills, setCofounderSkills] = useState(
+ user?.cofounderSkills || generateSkillMap()
+ );
+
+ const updateMySkills = (name, rank) => {
+ setMySkills(
+ mySkills.map((skill) =>
+ skill.name === name ? { ...skill, rank } : skill
+ )
+ );
+ };
+ const updateCofounderSkills = (name, rank) => {
+ setCofounderSkills(
+ cofounderSkills.map((skill) =>
+ skill.name === name ? { ...skill, rank } : skill
+ )
+ );
+ };
+
+ const save = () => {
+ db.insertOrUpdate(
+ "founders",
+ { username },
+ {
+ username,
+ firstName,
+ lastName,
+ location,
+ introduction,
+ contact,
+ skills: mySkills,
+ cofounderSkills,
+ }
+ );
+ db.commit();
+ window.location = "/";
+ };
+
+ return (
+ <>
+ Profile Settings:
+ {onboarding && (
+
+ Welcome! Please make sure to fill out the following form before
+ proceeding to match with potential cofounders.
+
+ )}
+
+
+ First Name
+ setFirstName(event.target.value)}
+ />
+
+
+ Last Name
+ setLastName(event.target.value)}
+ />
+
+
+
+ Location
+ setLocation(event.target.value)}
+ />
+
+
+ Introduction
+
+
+ Contact information
+
+ Experience and expectations:
+ {onboarding && (
+
+ Choose your expectations wisely!
+
+ )}
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default Settings;
diff --git a/src/ui/Card.js b/src/ui/Card.js
index f87532f..f99cfb5 100644
--- a/src/ui/Card.js
+++ b/src/ui/Card.js
@@ -1,54 +1,136 @@
-import React from 'react'
-import { Box, Image, Flex, Badge, Text, Button, StarIcon, Icon } from "@chakra-ui/core";
-
-
-const Card = ({title, author}) => {
-
- let rating = 3
- let count = 42
- return (
-
-
-
-
-
- New
-
-
-
-
- {title}
-
-
-
-
- By{" "}
+import React, { useState } from "react";
+import {
+ Box,
+ Avatar,
+ Icon,
+ IconButton,
+ Collapse,
+ Button,
+ Text,
+ Alert,
+ AlertTitle,
+} from "@chakra-ui/core";
+
+import { FaLocationArrow, FaRegClock } from "react-icons/fa";
+
+const randomGravatar = (id) =>
+ `https://www.gravatar.com/avatar/${id}?s=60&d=identicon&r=PG`;
+
+const MatchStatusButton = ({ status, onClick }) => {
+ switch (status) {
+ case "invited":
+ return (
+
+ );
+ case "completed":
+ return <>>;
+ default:
+ return (
+
+ );
+ }
+};
+const Card = ({
+ id,
+ username,
+ firstName,
+ lastName,
+ location,
+ introduction,
+ contact,
+ skills,
+ matchStatus,
+ sendInvitation,
+}) => {
+ const [show, setShow] = useState(false);
+ const handleToggle = () => setShow(!show);
+
+ return (
+
+ {matchStatus === "completed" && (
+
+ Cofounder matched!
+
+ )}
+
+
+ sendInvitation(username)}
+ />
+
+
+
+
+
+ {firstName} {lastName}
- {author}
-
-
-
- {Array(5)
- .fill("")
- .map((_, i) => (
-
- ))}
-
- {count} reviews
+
+
+ {location}
+
+ {matchStatus === "completed" && (
+
+ Contact information:
+ {contact}
+
+ )}
+
+
+
+ {introduction}
+
+
+
+
+
+ {skills.map(({ name, rank }, index) => (
+
+ {name}
+
+ {Array(5)
+ .fill("")
+ .map((_, i) => (
+
+ ))}
+
+
+ ))}
+
- )}
+
+ );
+};
- export default Card
\ No newline at end of file
+export default Card;
diff --git a/src/ui/Frame.js b/src/ui/Frame.js
index 8722cd1..5564445 100644
--- a/src/ui/Frame.js
+++ b/src/ui/Frame.js
@@ -1,20 +1,31 @@
-import React from "react"
-import { Box, Flex, Text } from "@chakra-ui/core"
-import { Link } from "react-router-dom"
-import Header from "./Header"
+import React from "react";
+import { Box, Button, Flex, Stack } from "@chakra-ui/core";
+import { Link } from "react-router-dom";
+import Header from "./Header";
const Frame = ({ children, username }) => {
return (
-
+
-
- Hello {username}! Log Out
-
+
+
+
+
+
+
{children}
- )
-}
-export default Frame
+ );
+};
+export default Frame;
diff --git a/src/ui/Header.js b/src/ui/Header.js
index c86674e..05c9489 100644
--- a/src/ui/Header.js
+++ b/src/ui/Header.js
@@ -1,25 +1,21 @@
-import React from 'react'
-import { Box, Flex, Link, Text } from "@chakra-ui/core"
-import Logo from "./Logo"
+import React from "react";
+import { Box, Flex, Link, Text } from "@chakra-ui/core";
+import Logo from "./Logo";
-const Header = ({children}) => {
+const Header = ({ children }) => {
+ return (
+
+
+ {children}
+
+ );
+};
- return
-
-
- {children}
-
-
-
-
-
-}
-
-export default Header
\ No newline at end of file
+export default Header;
diff --git a/src/ui/Logo.js b/src/ui/Logo.js
index 3ed421d..a2ad5c0 100644
--- a/src/ui/Logo.js
+++ b/src/ui/Logo.js
@@ -1,10 +1,15 @@
-import React from "react"
-import { Heading, Icon } from "@chakra-ui/core"
+import React from "react";
+import { Heading, Icon } from "@chakra-ui/core";
+import { Link } from "react-router-dom";
const Logo = () => {
- return
+ return (
+
+
OkFounder
-
-}
+
+
+ );
+};
-export default Logo
\ No newline at end of file
+export default Logo;
diff --git a/src/ui/SkillBox.js b/src/ui/SkillBox.js
new file mode 100644
index 0000000..45113a1
--- /dev/null
+++ b/src/ui/SkillBox.js
@@ -0,0 +1,33 @@
+import React from "react";
+import { Box, FormControl, Heading, Icon } from "@chakra-ui/core";
+
+export default ({ description, skills, update }) => {
+ return (
+
+
+ {description}:
+
+
+
+ {skills.map(({ name, rank }, index) => (
+
+ {name}
+
+ {Array(5)
+ .fill("")
+ .map((_, i) => (
+ update(name, i + 1)}
+ color={i < rank ? "teal.500" : "gray.300"}
+ />
+ ))}
+
+
+ ))}
+
+
+ );
+};