Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import "semantic-ui-css/semantic.min.css";
import "react-toastify/dist/ReactToastify.min.css";
import Map from "./components/map";
import styles from "./app.module.scss";
import SidePanel from "./components/side-panel";

toast.configure({
position: "bottom-center",
Expand All @@ -15,7 +16,7 @@ toast.configure({
function App() {
return (
<div className={styles.app}>
<Map />
<SidePanel />
</div>
);
}
Expand Down
1 change: 1 addition & 0 deletions src/components/side-panel/my-groups/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./my-groups";
17 changes: 17 additions & 0 deletions src/components/side-panel/my-groups/my-groups.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.content_section {
max-height: 20vh;
word-wrap: break-word;
overflow: auto;
}

.title_section {
width: 100%;
display: flex;
align-items: center;
}

.leave_button {
flex: 1;
display: flex;
justify-content: flex-end;
}
65 changes: 65 additions & 0 deletions src/components/side-panel/my-groups/my-groups.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Fragment, useState } from "react";
import { Accordion, Button, Icon } from "semantic-ui-react";
import { Group } from "../../../types";
import styles from "./my-groups.module.scss";

type Props = {
myGroup: Group[];
removeFromMyGroup: (groupToRemove: number) => void;
};

function MyGroups({ myGroup, removeFromMyGroup }: Props) {
const [activeIndex, setActiveIndex] = useState(-1);
const [hasLeaveButton, setLeaveButton] = useState(false);

const handleClick = (e: any, titleProps: any) => {
const { index } = titleProps;
const newIndex = activeIndex === index ? -1 : index;
const hasLeaveButton = newIndex >= 0;

setLeaveButton(hasLeaveButton);
setActiveIndex(newIndex);
};

const leaveGroup = (index: number) => {
removeFromMyGroup(index);
};

return (
<Accordion fluid styled>
{myGroup.map(({ groupName, pins }, index) => (
<Fragment key={index}>
<Accordion.Title
active={index === activeIndex}
index={index}
onClick={handleClick}
className={styles.title_section}
>
<Icon name="dropdown" />
{groupName}
{hasLeaveButton && index === activeIndex && (
<div className={styles.leave_button}>
<Button color="orange" onClick={() => leaveGroup(index)}>
Leave
</Button>
</div>
)}
</Accordion.Title>
<Accordion.Content active={index === activeIndex}>
<div className={styles.content_section}>
<ul>
{pins?.map(({ title, description }) => (
<li>
<b>{title}</b>: {description}
</li>
))}
</ul>
</div>
</Accordion.Content>
</Fragment>
))}
</Accordion>
);
}

export default MyGroups;
1 change: 1 addition & 0 deletions src/components/side-panel/public-groups/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./public-groups";
21 changes: 21 additions & 0 deletions src/components/side-panel/public-groups/public-groups.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.top_section {
margin-bottom: 10px;
}

.title_section {
width: 100%;
display: flex;
align-items: center;
}

.join_button {
flex: 1;
display: flex;
justify-content: flex-end;
}

.content_section {
max-height: 20vh;
word-wrap: break-word;
overflow: auto;
}
116 changes: 116 additions & 0 deletions src/components/side-panel/public-groups/public-groups.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { Fragment, useState, useRef } from "react";
import {
Accordion,
Icon,
Button,
Modal,
Form,
TextArea,
} from "semantic-ui-react";
import { Group } from "../../../types";
import styles from "./public-groups.module.scss";

type Props = {
publicGroups: Group[];
addNewGroup: (groupToAdd: Group) => void;
addIndexToMyGroup: (indexToAdd: number) => void;
};

function PublicGroups({ publicGroups, addNewGroup, addIndexToMyGroup }: Props) {
const [activeIndex, setActiveIndex] = useState(-1);
const [hasJoinButton, setJoinButton] = useState(false);
const [isModalOpen, setModalOpen] = useState(false);
const inputRef = useRef<HTMLInputElement>();

const handleClick = (e: any, titleProps: any) => {
const { index } = titleProps;
const newIndex = activeIndex === index ? -1 : index;
const hasJoinButton = newIndex >= 0;

setJoinButton(hasJoinButton);
setActiveIndex(newIndex);
};

const joinGroup = (index: number) => {
addIndexToMyGroup(index);
};

const toggleModal = () => {
setModalOpen(!isModalOpen);
};

const startGroup = () => {
const newGroupName = inputRef?.current?.value;

console.log(newGroupName);
if (newGroupName) {
addNewGroup({ groupName: newGroupName, members: [""] }); // users own name
} else {
alert("Unsuccessful");
}
setModalOpen(!isModalOpen);
};

return (
<>
<Modal open={isModalOpen}>
<Modal.Header>Enter a unique group name</Modal.Header>
<Modal.Content>
<Form.Field>
<Form.Input
input={{ ref: inputRef }}
size="large"
placeholder="Group name"
/>
</Form.Field>
</Modal.Content>
<Modal.Actions>
<Button onClick={toggleModal}>Cancel</Button>
<Button positive type="submit" onClick={startGroup}>
Start
</Button>
</Modal.Actions>
</Modal>

<div className={styles.top_section}>
<Button primary onClick={toggleModal}>
Start a group
</Button>
</div>

<Accordion fluid styled>
{publicGroups.map(({ groupName, members }, index) => (
<Fragment key={index}>
<Accordion.Title
active={index === activeIndex}
index={index}
onClick={handleClick}
className={styles.title_section}
>
<Icon name="dropdown" />
{groupName}
{hasJoinButton && index === activeIndex && (
<div className={styles.join_button}>
<Button positive onClick={() => joinGroup(index)}>
Join
</Button>
</div>
)}
</Accordion.Title>
<Accordion.Content active={index === activeIndex}>
<div className={styles.content_section}>
<ul>
{members.map((member) => (
<li>{member}</li>
))}
</ul>
</div>
</Accordion.Content>
</Fragment>
))}
</Accordion>
</>
);
}

export default PublicGroups;
5 changes: 4 additions & 1 deletion src/components/side-panel/side-panel.module.scss
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
.sidePanel {
.section {
padding: 2% 5%;
height: 100%;
background-color: rgb(255, 245, 234);
}
113 changes: 112 additions & 1 deletion src/components/side-panel/side-panel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,118 @@
import { Tab } from "semantic-ui-react";
import styles from "./side-panel.module.scss";
import PublicGroups from "./public-groups";
import MyGroups from "./my-groups";
import { Group } from "../../types";

const myGroup: Group[] = [
{
groupName: "Family",
pins: [{ title: "pin1", description: "asfvafdv" }],
members: ["max"],
},
{
groupName: "dorm friends",
pins: [{ title: "pin2", description: "jcfdaskbcnkdusvb" }],
members: ["max"],
},
{
groupName: "gang gang",
pins: [{ title: "pin3", description: "asfvdsacajsblisdnlisafdv" }],
members: ["max"],
},
{
groupName: "hot girl summer",
pins: [{ title: "pin4", description: "asfvafdv" }],
members: ["max"],
},
];

const publicGroups: Group[] = [
{
groupName: "public group 1",
pins: [{ title: "pin4", description: "never wanna give u up" }],
members: ["max"],
},
{
groupName: "best date spots",
pins: [{ title: "pin4", description: "never gonna let u down" }],
members: ["max"],
},
{
groupName: "great food here",
pins: [{ title: "pin4", description: "never gonna turn around" }],
members: ["max"],
},
{
groupName: "Max's friends only",
pins: [{ title: "pin4", description: "and desert you" }],
members: ["max"],
},
{
groupName: "Family",
pins: [{ title: "pin4", description: "asfvafdv" }],
members: ["max"],
},
{
groupName: "dorm friends",
pins: [{ title: "pin4", description: "jcfdaskbcnkdusvb" }],
members: ["max"],
},
{
groupName: "gang gang",
pins: [{ title: "pin4", description: "asfvdsacajsblisdnlisafdv" }],
members: ["max"],
},
{
groupName: "hot girl summer",
pins: [{ title: "pin4", description: "asfvafdv" }],
members: ["max"],
},
];

const addNewGroup = (groupToAdd: Group) => {
myGroup.push(groupToAdd);
publicGroups.push(groupToAdd);
};
const addIndexToMyGroup = (indexToAdd: number) => {
publicGroups[indexToAdd].members.push(""); // users own name
myGroup.push(publicGroups[indexToAdd]);
};
const removeFromMyGroup = (groupToRemove: number) => {
const removeIndex = myGroup.findIndex(
(group) => group === myGroup[groupToRemove],
);
myGroup.splice(removeIndex, 1);
groupToRemove;
};

const panes = [
{
menuItem: "Public Groups",
render: () => (
<Tab.Pane attached={false}>
<PublicGroups
publicGroups={publicGroups}
addNewGroup={addNewGroup}
addIndexToMyGroup={addIndexToMyGroup}
/>
</Tab.Pane>
),
},
{
menuItem: "My Groups",
render: () => (
<Tab.Pane attached={false}>
<MyGroups myGroup={myGroup} removeFromMyGroup={removeFromMyGroup} />
</Tab.Pane>
),
},
];

function SidePanel() {
return <div />;
return (
<Tab menu={{ secondary: true }} panes={panes} className={styles.section} />
);
}

export default SidePanel;
10 changes: 10 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export type Group = {
groupName: string,
pins?: Pin[],
members: string[]
};

export type Pin = {
title: string,
description: string,
};