diff options
author | elioat <{ID}+{username}@users.noreply.github.com> | 2025-07-16 10:37:53 -0400 |
---|---|---|
committer | elioat <{ID}+{username}@users.noreply.github.com> | 2025-07-16 10:37:53 -0400 |
commit | c9461b0e9cb6fdf854ce67ad72d635e5671cd182 (patch) | |
tree | adf636b7a99b998d188fd320d1c45ed6d98f55be /js/seed/src | |
parent | b1e0fb723ffe6928a6eaef0c61232598c570e272 (diff) | |
download | tour-master.tar.gz |
Diffstat (limited to 'js/seed/src')
-rw-r--r-- | js/seed/src/app.js | 40 | ||||
-rw-r--r-- | js/seed/src/dev.js | 74 |
2 files changed, 112 insertions, 2 deletions
diff --git a/js/seed/src/app.js b/js/seed/src/app.js index 5fd577c..34b4579 100644 --- a/js/seed/src/app.js +++ b/js/seed/src/app.js @@ -5,9 +5,11 @@ import { initialState, cloneState } from './state.js'; import { update } from './update.js'; import { view } from './view.js'; import { fetchPokemon } from './api.js'; +import { initDevMode } from './dev.js'; const root = document.getElementById('app'); let state = cloneState(initialState); +let dev; /** * Entrypoint for the app. @@ -90,6 +92,7 @@ function dispatch(action) { const prevState = state; state = update(state, action); if (devMode) { + dev.pushState(state); console.groupCollapsed(`Action: ${action.type}`); console.log('Payload:', action.payload); console.log('Prev state:', prevState); @@ -111,7 +114,7 @@ function handleInput(e) { /** * Handles form submission, triggers async fetch, and dispatches state updates. * - * Why handle async here? Keeps update/view pure and side-effect free, following functional programming best practices. + * Why handle async here? Keeps update/view pure and centralizes side-effect. */ async function handleSubmit(e) { e.preventDefault(); @@ -126,4 +129,37 @@ async function handleSubmit(e) { } // Initial render -doRender(); \ No newline at end of file +doRender(); + +// After devMode is set +if (devMode) { + dev = initDevMode({ + getState: () => state, + setState: s => { state = s; }, + render: doRender + }); +} + +function updateHistoryInfo() { + if (!devMode || !dev) return; + dev.update(); +} + +function setHistoryPointer(idx) { + const info = dev.getHistoryInfo(); + if (idx < 1 || idx > info.length) return; + const newState = dev.setPointer(idx - 1); + if (newState) { + state = newState; + doRender(); + updateHistoryInfo(); + } +} + +function handleSliderChange(e) { + setHistoryPointer(Number(e.target.value)); +} + +function handleStepperChange(e) { + setHistoryPointer(Number(e.target.value)); +} \ No newline at end of file diff --git a/js/seed/src/dev.js b/js/seed/src/dev.js new file mode 100644 index 0000000..ee1a6e7 --- /dev/null +++ b/js/seed/src/dev.js @@ -0,0 +1,74 @@ +// devMode.js +// Minimal, single-file dev mode with scriptable console API + +/** + * Initialize dev mode: exposes a scriptable API for stepping through state history. + * @param {object} opts + * @param {function} opts.getState - returns current app state + * @param {function} opts.setState - sets app state + * @param {function} opts.render - triggers app re-render + */ +export function initDevMode({ getState, setState, render }) { + let history = []; + let pointer = -1; + let firstLoad = true; + + function pushState(state) { + if (pointer < history.length - 1) history = history.slice(0, pointer + 1); + history.push(clone(state)); + pointer = history.length - 1; + logInstructions(); + } + function goTo(idx) { + if (idx < 0 || idx >= history.length) return; + pointer = idx; + setState(clone(history[pointer])); + render(); + logInstructions(); + } + function next() { + if (pointer < history.length - 1) goTo(pointer + 1); + } + function prev() { + if (pointer > 0) goTo(pointer - 1); + } + function get() { + return history[pointer]; + } + function clone(obj) { + return JSON.parse(JSON.stringify(obj)); + } + function table(obj) { + console.table(dev.history); + } + function logInstructions() { + if (firstLoad) { + console.log('[DevMode] State history debugger'); + console.log('Usage:'); + console.log('- dev.next() // step forward'); + console.log('- dev.prev() // step backward'); + console.log('- dev.goTo(n) // jump to state n (1-based)'); + console.log('- dev.get() // get current state'); + console.log('- dev.table() // display history as a table'); + console.log('- dev.history // array of all states'); + console.log('- dev.pointer // current pointer (0-based)'); + firstLoad = false; + } + } + + // Expose API globally for console use + window.dev = { + next, + prev, + goTo, + get, + table, + get pointer() { return pointer; }, + get history() { return history.slice(); }, + }; + + // Initial state + pushState(getState()); + + return { pushState }; +} \ No newline at end of file |