feat: The Big One UI #47
@@ -1,5 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import styles from "./SimpleProgram.module.css";
|
import styles from "./SimpleProgram.module.css";
|
||||||
|
import useProgramStore from "../../utils/programStore.ts";
|
||||||
|
|
||||||
/* ---------- Types ---------- */
|
/* ---------- Types ---------- */
|
||||||
|
|
||||||
@@ -36,10 +37,6 @@ type Phase = {
|
|||||||
triggers: KeywordTrigger[];
|
triggers: KeywordTrigger[];
|
||||||
};
|
};
|
||||||
|
|
||||||
type SimpleProgramProps = {
|
|
||||||
phases: Phase[];
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ---------- Reusable UI ---------- */
|
/* ---------- Reusable UI ---------- */
|
||||||
|
|
||||||
type BoxProps = {
|
type BoxProps = {
|
||||||
@@ -63,11 +60,7 @@ const GoalList: React.FC<{ goals: Goal[] }> = ({ goals }) => {
|
|||||||
<ul className={styles.iconList}>
|
<ul className={styles.iconList}>
|
||||||
{goals.map((goal) => (
|
{goals.map((goal) => (
|
||||||
<li key={goal.id}>
|
<li key={goal.id}>
|
||||||
<span
|
<span className={goal.achieved ? styles.successIcon : styles.failIcon}>
|
||||||
className={
|
|
||||||
goal.achieved ? styles.successIcon : styles.failIcon
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{goal.achieved ? "✔" : "✖"}
|
{goal.achieved ? "✔" : "✖"}
|
||||||
</span>
|
</span>
|
||||||
{goal.description}
|
{goal.description}
|
||||||
@@ -77,11 +70,8 @@ const GoalList: React.FC<{ goals: Goal[] }> = ({ goals }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const TriggerList: React.FC<{ triggers: KeywordTrigger[] }> = ({
|
const TriggerList: React.FC<{ triggers: KeywordTrigger[] }> = ({ triggers }) => {
|
||||||
triggers,
|
if (triggers.length === 0) return <p className={styles.empty}>No triggers defined.</p>;
|
||||||
}) => {
|
|
||||||
if (triggers.length === 0)
|
|
||||||
return <p className={styles.empty}>No triggers defined.</p>;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ul className={styles.iconList}>
|
<ul className={styles.iconList}>
|
||||||
@@ -133,48 +123,37 @@ const PhaseGrid: React.FC<{ phase: Phase }> = ({ phase }) => {
|
|||||||
|
|
||||||
/* ---------- Main Component ---------- */
|
/* ---------- Main Component ---------- */
|
||||||
|
|
||||||
const SimpleProgram: React.FC<SimpleProgramProps> = ({ phases }) => {
|
const SimpleProgram: React.FC = () => {
|
||||||
|
// Get the phases from the program store
|
||||||
|
const phases = useProgramStore((state) => state.currentProgram.phases) as Phase[];
|
||||||
const [phaseIndex, setPhaseIndex] = React.useState(0);
|
const [phaseIndex, setPhaseIndex] = React.useState(0);
|
||||||
|
|
||||||
|
// If no phases are available, display a message
|
||||||
|
if (phases.length === 0) return <p className={styles.empty}>No program loaded.</p>;
|
||||||
|
|
||||||
const phase = phases[phaseIndex];
|
const phase = phases[phaseIndex];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<header className={styles.header}>
|
<header className={styles.header}>
|
||||||
<button
|
|
||||||
className={styles.backButton}
|
|
||||||
onClick={() => {
|
|
||||||
window.history.back();
|
|
||||||
setTimeout(() => {
|
|
||||||
window.history.forward();
|
|
||||||
}, 5);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
← Back
|
|
||||||
</button>
|
|
||||||
<h2>
|
<h2>
|
||||||
Phase {phaseIndex + 1} / {phases.length}: {phase.label}
|
Phase {phaseIndex + 1} / {phases.length}: {phase.label}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div className={styles.controls}>
|
<div className={styles.controls}>
|
||||||
<button
|
<button disabled={phaseIndex === 0} onClick={() => setPhaseIndex(i => i - 1)}>
|
||||||
disabled={phaseIndex === 0}
|
|
||||||
onClick={() => setPhaseIndex((i) => i - 1)}
|
|
||||||
>
|
|
||||||
◀ Prev
|
◀ Prev
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button disabled={phaseIndex === phases.length - 1} onClick={() => setPhaseIndex(i => i + 1)}>
|
||||||
disabled={phaseIndex === phases.length - 1}
|
|
||||||
onClick={() => setPhaseIndex((i) => i + 1)}
|
|
||||||
>
|
|
||||||
Next ▶
|
Next ▶
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
<PhaseGrid phase={phase} />
|
<PhaseGrid phase={phase} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -181,21 +181,23 @@ function graphReducer() {
|
|||||||
*/
|
*/
|
||||||
function VisProgPage() {
|
function VisProgPage() {
|
||||||
const [showSimpleProgram, setShowSimpleProgram] = useState(false);
|
const [showSimpleProgram, setShowSimpleProgram] = useState(false);
|
||||||
const [phases, setPhases] = useState<any[]>([]);
|
const setProgramState = useProgramStore((state) => state.setProgramState);
|
||||||
|
|
||||||
const runProgram = () => {
|
const runProgram = () => {
|
||||||
const reducedPhases = graphReducer();
|
const phases = graphReducer(); // reduce graph
|
||||||
setPhases(reducedPhases);
|
setProgramState({ phases }); // <-- save to store
|
||||||
setShowSimpleProgram(true);
|
setShowSimpleProgram(true); // show SimpleProgram
|
||||||
runProgramm();
|
runProgramm(); // send to backend if needed
|
||||||
};
|
};
|
||||||
|
|
||||||
if (showSimpleProgram) {
|
if (showSimpleProgram) {
|
||||||
return (
|
return (
|
||||||
<SimpleProgram
|
<div>
|
||||||
phases={phases}
|
<button onClick={() => setShowSimpleProgram(false)}>
|
||||||
|
Back to Editor ◀
|
||||||
/>
|
</button>
|
||||||
|
<SimpleProgram/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user