Skip to content

Commit

Permalink
Merge pull request #334 from ocftw/feature/add-redux-store-and-wizard
Browse files Browse the repository at this point in the history
  • Loading branch information
ben196888 committed Jul 1, 2024
2 parents 299aec5 + 35aee6f commit ea13184
Show file tree
Hide file tree
Showing 51 changed files with 1,536 additions and 1,129 deletions.
4 changes: 3 additions & 1 deletion packages/webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
"@mui/lab": "^5.0.0-alpha.170",
"@mui/material": "^5.15.19",
"@mui/material-nextjs": "^5.15.11",
"@reduxjs/toolkit": "^2.2.5",
"boardgame.io": "^0.50.2",
"next": "14.2.3",
"react": "^18",
"react-dom": "^18"
"react-dom": "^18",
"react-redux": "^9.1.2"
},
"devDependencies": {
"@types/jest": "^29.5.12",
Expand Down
18 changes: 18 additions & 0 deletions packages/webapp/src/app/StoreProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use client'
import { useRef } from 'react'
import { Provider } from 'react-redux'
import { makeStore, AppStore } from '../lib/store'

export default function StoreProvider({
children
}: {
children: React.ReactNode
}) {
const storeRef = useRef<AppStore>()
if (!storeRef.current) {
// Create the store instance the first time this renders
storeRef.current = makeStore()
}

return <Provider store={storeRef.current}>{children}</Provider>
}
9 changes: 6 additions & 3 deletions packages/webapp/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import DevView from "@/components/DevView";
import StoreProvider from "./StoreProvider";

const getIsLocal = async () => {
'use server'
Expand All @@ -9,8 +10,10 @@ const getIsLocal = async () => {
export default async function Home() {
const isLocal = await getIsLocal();
return (
<main>
<DevView isLocal={isLocal} />
</main>
<StoreProvider>
<main>
<DevView isLocal={isLocal} />
</main>
</StoreProvider>
);
}
105 changes: 105 additions & 0 deletions packages/webapp/src/components/ActionBoard/ActionBoard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import React from 'react';
import { Button, Toolbar } from "@mui/material";
import { Dispatch, createSelector } from "@reduxjs/toolkit";
import { Page, hasNextPage, isPageCancellable, wizardActions } from '@/lib/reducers/wizard';
import { connect } from 'react-redux';
import { selectWizard } from '@/lib/selector';

enum ActionName {
CREATE_PROJECT = 'CREATE_PROJECT',
RECRUIT = 'RECRUIT',
CONTRIBUTE_JOINED_PROJECTS = 'CONTRIBUTE_JOINED_PROJECTS',
CONTRIBUTE_OWNED_PROJECTS = 'CONTRIBUTE_OWNED_PROJECTS',
REMOVE_AND_REFILL_JOBS = 'REMOVE_AND_REFILL_JOBS',
MIRROR = 'MIRROR',
}

const getPagesByActionName = (name: ActionName): Page[] => {
switch (name) {
case ActionName.CREATE_PROJECT:
return [
{
isCancellable: true,
requiredSteps: {
'player--hand--project': {
type: 'player--hand--project',
limit: 1,
}
},
toggledSteps: [],
},
{
isCancellable: true,
requiredSteps: {
'table--active-job': {
type: 'table--active-job',
limit: 1,
}
},
toggledSteps: [],
},
];
default:
return [];
}
}

interface StateProps {
showCancelBtn: boolean;
showConfirmBtn: boolean;
showSubmitBtn: boolean;
}

interface DispatchProps {
onCreateProjectActionClick: () => void;
onConfirmBtnClick: () => void;
onCancelBtnClick: () => void;
onSubmitBtnClick: () => void;
}

type Props = StateProps & DispatchProps;

const ActionBoard: React.FC<Props> = ({ showCancelBtn, showConfirmBtn, showSubmitBtn, onCancelBtnClick, onConfirmBtnClick, onSubmitBtnClick }) => {
return (
<Toolbar>
{showCancelBtn && <Button onClick={onCancelBtnClick}> Cancel </Button>}
{showConfirmBtn && <Button onClick={onConfirmBtnClick}>Confirm</Button>}
{showSubmitBtn && <Button onClick={onSubmitBtnClick}>Submit</Button>}
</Toolbar>
)
}

const mapStateToProps = createSelector(
selectWizard, (wizard): StateProps => {
const showCancelBtn = isPageCancellable(wizard);
const showConfirmBtn = hasNextPage(wizard);
const showSubmitBtn = !hasNextPage(wizard);
return {
showCancelBtn,
showConfirmBtn,
showSubmitBtn,
}
});

const mapDispatchToProps = (dispatch: Dispatch) => {
const onCreateProjectActionClick = () => {
dispatch(wizardActions.init(getPagesByActionName(ActionName.CREATE_PROJECT)));
}
const onConfirmBtnClick = () => {
dispatch(wizardActions.nextPage());
}
const onCancelBtnClick = () => {
dispatch(wizardActions.prevPage());
}
const onSubmitBtnClick = () => {
dispatch(wizardActions.clear());
}
return {
onCreateProjectActionClick,
onConfirmBtnClick,
onCancelBtnClick,
onSubmitBtnClick,
}
}

export default connect(mapStateToProps, mapDispatchToProps)(ActionBoard);
16 changes: 10 additions & 6 deletions packages/webapp/src/components/BoardGame.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import { Client, BoardProps } from 'boardgame.io/react';
import { SocketIO, Local } from 'boardgame.io/multiplayer'
import { OpenStarTerVillage } from '@/game';
import game, { GameState } from '@/game';
import Table from '@/components/Table/Table';
import Players from '@/components/Players/Players';
import DevActions from '@/components/DevActions/DevActions';
import ActionBoard from './ActionBoard/ActionBoard';

const Board: React.FC<BoardProps<OpenStarTerVillageType.State.Root>> = (props) => {
const Board: React.FC<BoardProps<GameState>> = (props) => {
const { G, ctx, debug } = props;
return (
<div className='Board'>
<Table {...props} />
<Players {...props} />
<DevActions {...props} />
<ActionBoard />
<Table table={G.table} />
<Players players={G.players} />
{debug && <DevActions {...props} />}
</div>
);
}

const Boardgame: React.FC<{ isLocal: boolean} & React.ComponentProps<ReturnType<typeof Client>>> = ({ isLocal, ...props }) => {
const multiplayer = isLocal ? Local() : SocketIO({ server: 'localhost:8000' });

const BoardgameComponent = Client({ game:OpenStarTerVillage,
const BoardgameComponent = Client({
game,
board: Board,
multiplayer,
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Box, Stack, TextField } from "@mui/material";
import React from "react";

interface Props {
value: number;
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
}

const ContributionValueInputBox: React.FC<Props> = ({ value, onChange }) => (
<Stack direction="row" spacing={2}>
<Box component='label'>Value</Box>
<TextField
type="number"
InputProps={{ inputProps: { min: 0, max: 5 } }}
value={value}
onChange={onChange}
/>
</Stack>
);

export default ContributionValueInputBox;
Loading

0 comments on commit ea13184

Please sign in to comment.