Skip to content

Commit

Permalink
feat(movex-docs movex-demo): ✨ wIP - Making progress with the examples
Browse files Browse the repository at this point in the history
  • Loading branch information
GabrielCTroia committed Jul 7, 2023
1 parent e0745c3 commit 61c4146
Show file tree
Hide file tree
Showing 11 changed files with 508 additions and 208 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,6 @@ yalc.lock
.next

# Typescript
tsconfig.tsbuildinfo
tsconfig.tsbuildinfo

.movex
154 changes: 154 additions & 0 deletions apps/movex-demo/modules/playground/Preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
export const x = 1;

// import React, { useRef, useEffect, useState } from "react";
// import * as runtime from "react/jsx-runtime";
// // import { compile, run } from "@mdx-js/mdx";
// // import { remarkCodeHike } from "@code-hike/mdx";
// // import { CH } from "@code-hike/mdx/components";
// import "@code-hike/mdx/styles.css";
// // import { ErrorBoundary } from "react-error-boundary";
// // import { toHash } from "./hash";

// export function Preview(props) {
// return (
// <div className={`preview ${props.standalone ? "standalone" : ""}`}>
// {/* <ErrorBoundary */}
// {/* resetKeys={[props.input.mdx, props.input.css, props.input.config]}
// FallbackComponent={ErrorFallback}
// > */}
// <InnerPreview {...props} />
// {/* </ErrorBoundary> */}
// </div>
// );
// }
// function ErrorFallback({ error }) {
// return (
// <div className="preview-error">
// <h3>Runtime Error:</h3>
// <pre>{String(error)}</pre>
// </div>
// );
// }

// async function compileAndRun(input) {
// try {
// const c = await compile(input.mdx, {
// outputFormat: "function-body",
// remarkPlugins: [
// [
// // remarkCodeHike,
// {
// ...input.config,
// autoImport: false,
// theme: input.config.theme,
// },
// ],
// ],
// });
// const x = await run(String(c), runtime);
// return { content: x.default, error: undefined };
// } catch (e) {
// return { content: undefined, error: e.message };
// }
// }

// let effectId = 0;

// function useInput(input) {
// const [{ Content, error }, setState] = useState({
// Content: undefined,
// error: undefined,
// });
// const [loading, setLoading] = useState(true);
// useEffect(() => {
// const id = effectId;
// // console.log("compiling...", id);
// setLoading(true);
// compileAndRun(input).then(({ content, error }) => {
// // console.log("compiled", id, error);
// if (id !== effectId) {
// // console.log("skipping", id);
// return;
// }
// setState((state) => ({
// Content: content || state.Content,
// error,
// }));
// setLoading(false);
// });
// return () => {
// // console.log("cancelling", id);
// effectId++;
// };
// }, [input.mdx, input.css, input.config]);

// return { Content, error, loading };
// }

// function InnerPreview({ input, standalone, refreshKey }) {
// const { Content, error, loading } = useInput(input);
// // console.log(error);
// return (
// <>
// <style>{input.css}</style>
// {error ? (
// <div className="compile-error">
// <h3>Compliation Error:</h3>
// <pre>{error}</pre>
// </div>
// ) : null}
// {/* {standalone ? (
// <a href={`/#${toHash(input)}`} className="standalone-link">
// <PlaygroundIcon />
// </a>
// ) : (
// <a href={`/?preview=1#${toHash(input)}`} className="standalone-link">
// <ExternalIcon />
// </a>
// )} */}
// <div className={`preview-container ${error ? "with-error" : ""}`}>
// <div style={{ opacity: loading ? 1 : 0 }} className="loading-border" />
// {Content ? <Content components={{ CH }} key={refreshKey} /> : null}
// </div>
// </>
// );
// }

// function ExternalIcon() {
// return (
// <svg
// className="icon"
// fill="none"
// stroke="currentColor"
// viewBox="0 0 24 24"
// xmlns="http://www.w3.org/2000/svg"
// >
// <title>Open in new window</title>
// <path
// strokeLinecap="round"
// strokeLinejoin="round"
// strokeWidth={2}
// d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
// />
// </svg>
// );
// }
// function PlaygroundIcon() {
// return (
// <svg
// className="icon"
// fill="none"
// stroke="currentColor"
// viewBox="0 0 24 24"
// xmlns="http://www.w3.org/2000/svg"
// >
// <title>Open playground</title>
// <path
// strokeLinecap="round"
// strokeLinejoin="round"
// strokeWidth={2}
// d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"
// />
// </svg>
// );
// }
161 changes: 161 additions & 0 deletions apps/movex-demo/modules/rock-paper-scissors/RPSUi.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import { MovexBoundResourceFromConfig } from 'movex-react';
import { useCallback, useEffect, useMemo } from 'react';
import { Rps, movexConfig } from 'movex-examples';
import { invoke, logsy, toResourceIdentifierStr } from 'movex-core-util';

const { selectAvailableLabels, toOppositeLabel } = Rps;

type Props = {
boundResource: MovexBoundResourceFromConfig<
typeof movexConfig['resources'],
'rps'
>;
userId: string;
buttonClassName?: string;
containerClassName?: string;
};

export const RPSUi: React.FC<Props> = ({ boundResource, userId, ...props }) => {
const { state, dispatch, dispatchPrivate } = boundResource;

const myPlayerLabel = useMemo((): Rps.PlayerLabel | undefined => {
if (state.players.playerA?.id === userId) {
return 'playerA';
}

if (state.players.playerB?.id === userId) {
return 'playerB';
}

return undefined;
}, [state.players, userId]);

const oppnentPlayerLabel = useMemo(() => {
return myPlayerLabel ? toOppositeLabel(myPlayerLabel) : undefined;
}, [myPlayerLabel]);

// Add Player
useEffect(() => {
// TODO: here there is a major issue, as selectAvailableLables works with local state
// but it needs to check on the actual (master) state. How to solve this?
// add an api to be able to read master state seperately?

// Or in this case change the strategy altogether, and work with master generated values, in which case
// the local optimistic state udate gets turned off by default, so that means it will wait for the real staet to update.
// Kinda like a dispatchAndWait
const availableLabels = selectAvailableLabels(state);

if (
state.players.playerA?.id === userId ||
state.players.playerB?.id === userId
) {
return;
}

if (availableLabels.length === 0) {
logsy.warn('Player Slots taken');

return;
}

dispatch({
type: 'addPlayer',
payload: {
id: userId,
playerLabel: availableLabels[0],
atTimestamp: new Date().getTime(),
},
});
}, [userId, state]);

const submit = useCallback(
(play: Rps.RPS) => {
if (!myPlayerLabel) {
console.warn('Not A Player');
return;
}

dispatchPrivate(
{
type: 'submit',
payload: {
playerLabel: myPlayerLabel,
rps: play,
},
isPrivate: true,
},
{
type: 'setReadySubmission',
payload: {
playerLabel: myPlayerLabel,
},
}
);
},
[dispatchPrivate, myPlayerLabel]
);

const winner = useMemo(() => {
if (!state.winner) {
return undefined;
}

if (state.winner === '1/2') {
return '1/2';
}

const {
submissions: { playerA },
} = state;

if (playerA.play === state.winner) {
return state.players.playerA.label;
}

return state.players.playerB.label;
}, [state.winner]);

return (
<div className="w-full">
{state.winner ? (
<div>
<h3>
{winner === '1/2'
? 'Draw'
: winner === myPlayerLabel
? 'You Won'
: 'You Lost'}
</h3>
<button
onClick={() => {
dispatch({
type: 'playAgain',
});
}}
>
Play Again
</button>
</div>
) : (
<div className='flex align-stretch'>
{oppnentPlayerLabel &&
state.submissions[oppnentPlayerLabel]?.play && (
<div>Opponent Submitted</div>
)}
<div >
<button className="text-7xl hover:text-8xl" onClick={() => submit('rock')}>
👊
</button>
</div>
<button className="text-7xl hover:text-8xl" onClick={() => submit('paper')}></button>
<button className="text-7xl hover:text-8xl" onClick={() => submit('scissors')}>✌️</button>
</div>
)}
{/* <br /> */}
{/* <div>
<pre>rid: {toResourceIdentifierStr(boundResource.rid)}</pre>
<pre>{JSON.stringify(state, null, 2)}</pre>
</div> */}
</div>
);
};
4 changes: 2 additions & 2 deletions apps/movex-demo/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import '../globals.css';

function CustomApp({ Component, pageProps }: AppProps) {
return (
<MovexLocalMasterProvider movexDefinition={movexConfig}>
<>
<Head>
<title>Welcome to movex-demo!</title>
</Head>
<main className="app">
<Component {...pageProps} />
<Analytics />
</main>
</MovexLocalMasterProvider>
</>
);
}

Expand Down
1 change: 1 addition & 0 deletions apps/movex-demo/pages/local/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export function Index() {
*/
return (
<StyledPage>
yeeeep
<div
style={{
display: 'flex',
Expand Down
Loading

0 comments on commit 61c4146

Please sign in to comment.