Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add routing and jsx scaffolding #4

Merged
merged 1 commit into from
Mar 21, 2024
Merged
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
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
"typecheck": "tsc --noEmit -p tsconfig.json"
},
"dependencies": {
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.0",
"@types/react-router-dom": "^5.3.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.0"
"react-router-dom": "^6.22.3"
},
"devDependencies": {
"@commitlint/cli": "^19.2.0",
Expand Down
39 changes: 30 additions & 9 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import "./App.css";
import { Header } from "./components/header.tsx";
import { Production } from "./components/production.tsx";
import { DeviceSelector } from "./components/device-select.tsx";
import { ErrorPage } from "./components/router-error.tsx";
import { useDevicePermissions } from "./hooks/device-permission.ts";
import { LandingPage } from "./components/landing-page/landing-page.tsx";

const router = createBrowserRouter([
{
path: "/",
element: <LandingPage />,
errorElement: <ErrorPage />,
},
{
path: "production/:productionId",
// loader: productionLoader,
element: <Production />,
},
]);

const App = () => {
return (
<>
<Header />
<DeviceSelector />
<Production />
</>
);
const { denied, permission } = useDevicePermissions();

if (denied) {
return (
<div>
Permission denied, reload browser and/or reset permissions to try again.
</div>
);
}

if (!permission) return <div>Waiting for device permissions</div>;

return <RouterProvider router={router} />;
};

export default App;
29 changes: 29 additions & 0 deletions src/components/landing-page/create-production.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { DisplayContainerHeader } from "./display-container-header.tsx";
import {
DecorativeLabel,
FormContainer,
FormInput,
FormLabel,
SubmitButton,
} from "./form-elements.tsx";

export const CreateProduction = () => {
return (
<FormContainer>
<DisplayContainerHeader>Create Production</DisplayContainerHeader>
<FormLabel>
<DecorativeLabel>Production Name</DecorativeLabel>
<FormInput type="text" value="" placeholder="Production Name" />
</FormLabel>
<FormLabel>
<DecorativeLabel>Line</DecorativeLabel>
<FormInput type="text" value="Editorial" placeholder="Line Name" />
</FormLabel>
<FormLabel>
<DecorativeLabel>Line</DecorativeLabel>
<FormInput type="text" value="Production" placeholder="Line Name" />
</FormLabel>
<SubmitButton type="submit">Create Production</SubmitButton>
</FormContainer>
);
};
8 changes: 8 additions & 0 deletions src/components/landing-page/display-container-header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import styled from "@emotion/styled";

export const DisplayContainerHeader = styled.h2`
font-size: 3rem;
font-weight: bold;
line-height: 1;
margin: 0 0 1rem;
`;
31 changes: 31 additions & 0 deletions src/components/landing-page/form-elements.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import styled from "@emotion/styled";

export const FormContainer = styled.div``;

export const FormInput = styled.input`
width: 100%;
`;

export const FormSelect = styled.select`
width: 100%;
`;

export const FormLabel = styled.label`
display: block;
padding: 0 0 1rem;
input,
select {
font-size: 1.6rem;
display: inline-block;
}
`;

export const DecorativeLabel = styled.span`
display: block;
white-space: nowrap;
padding: 0 1rem 1rem 0;
`;

export const SubmitButton = styled.button`
font-size: 1.6rem;
`;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import styled from "@emotion/styled";
import { FC } from "react";
import { backgroundColour } from "../css-helpers/defaults";
import { backgroundColour } from "../../css-helpers/defaults.ts";

const HeaderWrapper = styled.div`
width: 100%;
Expand Down
49 changes: 49 additions & 0 deletions src/components/landing-page/join-production.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { DisplayContainerHeader } from "./display-container-header.tsx";
import {
DecorativeLabel,
FormLabel,
FormContainer,
FormInput,
FormSelect,
SubmitButton,
} from "./form-elements.tsx";

export const JoinProduction = () => {
return (
<FormContainer>
<DisplayContainerHeader>Join Production</DisplayContainerHeader>
<FormLabel>
<DecorativeLabel>Production ID</DecorativeLabel>
<FormInput type="text" placeholder="Production ID" value="" />
</FormLabel>
<FormLabel>
<DecorativeLabel>Username</DecorativeLabel>
<FormInput type="text" placeholder="Username" value="" />
</FormLabel>
<FormLabel>
<DecorativeLabel>Input</DecorativeLabel>
<FormSelect>
<option>Mic 1</option>
<option>Mic 2</option>
</FormSelect>
</FormLabel>
<FormLabel>
<DecorativeLabel>Output</DecorativeLabel>
<FormSelect>
<option>Speaker 1</option>
<option>Speaker 2</option>
</FormSelect>
</FormLabel>

<FormLabel>
<DecorativeLabel>Line</DecorativeLabel>
<FormSelect>
<option>Line 1</option>
<option>Line 2</option>
</FormSelect>
</FormLabel>

<SubmitButton type="submit">Join</SubmitButton>
</FormContainer>
);
};
38 changes: 38 additions & 0 deletions src/components/landing-page/landing-page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import styled from "@emotion/styled";
import { Header } from "./header.tsx";
import { JoinProduction } from "./join-production.tsx";
import { CreateProduction } from "./create-production.tsx";
import { ProductionsList } from "./productions-list.tsx";

const FlexContainer = styled.div`
display: flex;
`;

const DisplayContainer = styled.div`
flex-basis: 100%;
display: flex;

&:first-of-type {
border-right: 1px solid white;
padding: 5rem 2rem 5rem 5rem;
justify-content: flex-end;
}
&:last-of-type {
padding: 5rem 5rem 5rem 2rem;
}
`;

export const LandingPage = () => (
<>
<Header />
<FlexContainer>
<DisplayContainer>
<JoinProduction />
</DisplayContainer>
<DisplayContainer>
<CreateProduction />
</DisplayContainer>
</FlexContainer>
<ProductionsList />
</>
);
69 changes: 69 additions & 0 deletions src/components/landing-page/productions-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import styled from "@emotion/styled";

const ProductionListContainer = styled.div`
display: flex;
padding: 2rem 0 2rem 2rem;
flex-wrap: wrap;
`;

const ProductionItem = styled.div`
flex: 1 0 calc(25% - 2rem);
min-width: 20rem;
border: 1px solid #424242;
border-radius: 0.5rem;
padding: 2rem;
margin: 0 2rem 2rem 0;
`;

const ProductionName = styled.div`
font-size: 1.4rem;
font-weight: bold;
margin: 0 0 1rem;
word-break: break-word;
`;

const ProductionId = styled.div`
font-size: 2rem;
color: #9e9e9e;
`;

export const ProductionsList = () => {
return (
<ProductionListContainer>
<ProductionItem>
<ProductionName>Mello</ProductionName>
<ProductionId>123</ProductionId>
</ProductionItem>
<ProductionItem>
<ProductionName>Bolibompa</ProductionName>
<ProductionId>4</ProductionId>
</ProductionItem>
<ProductionItem>
<ProductionName>Nyheterna</ProductionName>
<ProductionId>928</ProductionId>
</ProductionItem>
<ProductionItem>
<ProductionName>Sikta mot Stjärnorna</ProductionName>
<ProductionId>38974</ProductionId>
</ProductionItem>
<ProductionItem>
<ProductionName>Idol</ProductionName>
<ProductionId>5</ProductionId>
</ProductionItem>
<ProductionItem>
<ProductionName>
IdolIdol Idol Idol Idol Idol Idol Idol Idol Idol Idol Idol Idol Idol
Idol Idol Idol Idol Idol Idol Idol Idol Idol Idol
</ProductionName>
<ProductionId>5</ProductionId>
</ProductionItem>
<ProductionItem>
<ProductionName>
IdolIdolIdolIdolIdolIdolIdolIdolIdolIdolIdolIdolIdolIdol
IdolIdolIdolIdolIdolIdolIdolIdolIdolIdol
</ProductionName>
<ProductionId>5</ProductionId>
</ProductionItem>
</ProductionListContainer>
);
};
4 changes: 4 additions & 0 deletions src/components/production.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@ const UserList = styled.div`
`;

export const Production: FC = () => {
// const { participants } = useLoaderData();
// Mute/Unmute mic
// Mute/Unmute speaker
// Show active sink and mic
return <UserList>A User</UserList>;
};
19 changes: 19 additions & 0 deletions src/components/router-error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useRouteError } from "react-router-dom";

export const ErrorPage = () => {
const error = useRouteError();
console.error(error);

if (error instanceof Error) {
return (
<div id="error-page">
<h1>Oops!</h1>
<p>Sorry, an unexpected error has occurred.</p>
<p>
<i>{`${error.name} ${error.message}`}</i>
</p>
</div>
);
}
return <div>{`Oops ${JSON.stringify(error)}`}</div>;
};
21 changes: 21 additions & 0 deletions src/hooks/device-permission.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useEffect, useState } from "react";

export const useDevicePermissions = () => {
const [permission, setPermission] = useState(false);
const [denied, setDenied] = useState(false);

useEffect(() => {
navigator.mediaDevices
.getUserMedia({ audio: true, video: false })
.then(() => {
setDenied(false);
setPermission(true);
})
.catch(() => {
setDenied(true);
setPermission(false);
});
}, []);

return { permission, denied };
};
Loading