diff options
Diffstat (limited to 'ai_prompt.md')
| -rw-r--r-- | ai_prompt.md | 521 |
1 files changed, 521 insertions, 0 deletions
diff --git a/ai_prompt.md b/ai_prompt.md new file mode 100644 index 0000000..89660db --- /dev/null +++ b/ai_prompt.md @@ -0,0 +1,521 @@ +## Me + +> Context: +> - <rules>.rules/daisyui.md</rules> +> - <rules>.rules/project.md</rules> +> - <file>reference/tire-sizes.json</file> +> - <file>reference/howto.mdown</file> +> - <group>files</group> + +I need you to use @{files} to build a frontend. + +It will contain the following +- 2 dropdowns: one for rim size and one for tire size + - the values in this dropdowns will come from the json file I have given you. place this json file in an appropriate spot in the project +- each of those dropdowns will have an accompanying text box + - these textboxes will only accept numbers + - when a dropdown option is selected, it will fill the text box with the corresponding value from the json + - whenever the textbox value is manually updated by the user, the dropdown should update automatically to match the number with the first matching value. if there are no matching values instead set the dropdown to a value called "custom". This "custom" value should be at the bottom of the selections. If custom is selected in the dropdown by a user nothing should happen or change in the text box +- an output box which will have the resulting value from the options selected based on the equation in the given howto.mdown file + +you may completely remove the default given code and start from scratch as you see fit. + +## CodeCompanion (Copilot) + + + +I'll start by exploring the project structure to understand what exists, then build the app. + +Searched files for `**/*`, 50 results +``` +.dockerignore +.gitignore +.tool-versions +Dockerfile +README.md +docker-compose.yml +docker-entrypoint.sh +docker_readme.md +eslint.config.js +index.html +package-lock.json +package.json +tsconfig.app.json +tsconfig.json +tsconfig.node.json +vite.config.ts +.git/COMMIT_EDITMSG +.git/HEAD +.git/config +.git/description +.git/index +.rules/daisyui.md +.rules/project.md +node_modules/.package-lock.json +public/vite.svg +reference/howto.mdown +reference/tire-sizes.json +src/App.css +src/App.tsx +src/index.css +src/main.tsx +.git/hooks/applypatch-msg.sample +.git/hooks/commit-msg.sample +.git/hooks/fsmonitor-watchman.sample +.git/hooks/post-update.sample +.git/hooks/pre-applypatch.sample +.git/hooks/pre-commit.sample +.git/hooks/pre-merge-commit.sample +.git/hooks/pre-push.sample +.git/hooks/pre-rebase.sample +.git/hooks/pre-receive.sample +.git/hooks/prepare-commit-msg.sample +.git/hooks/push-to-checkout.sample +.git/hooks/sendemail-validate.sample +.git/hooks/update.sample +.git/info/exclude +.git/logs/HEAD +node_modules/acorn/CHANGELOG.md +node_modules/acorn/LICENSE +node_modules/acorn/README.md +``` + + +Read file `package.json` (0 - end) + + +Read file `src/index.css` (0 - end) + + +Read file `src/App.tsx` (0 - end) + + +Read file `src/App.css` (0 - end) + + +Read file `src/main.tsx` (0 - end) + + +Read file `index.html` (0 - end) + + +Read file `vite.config.ts` (0 - end) + + +Now I have a clear picture. Let me plan the implementation: + +1. Copy the tire sizes JSON into `src/data/tire_sizes.json` +2. Create a TypeScript types file for the data +3. Create a `circumference_calculator` component +4. Rewrite `App.tsx` to use it +5. Clean up `index.css` (remove custom styles, keep Tailwind+daisyUI) +6. Delete `App.css` and the assets folder + +Let me build this step by step: + +Searched files for `src/assets/*`, 1 results +``` +src/assets/react.svg +``` + + +Created file `src/data/tire_sizes.json` + +````json +{ + "wheel_sizes": [ + { "label": "12.5\"", "diameter_mm": 203 }, + { "label": "14\"", "diameter_mm": 254 }, + { "label": "16\"", "diameter_mm": 305 }, + { "label": "20\"", "diameter_mm": 406 }, + { "label": "24\" BMX/Kids Bikes", "diameter_mm": 507 }, + { "label": "24\" Terry Bicycles", "diameter_mm": 520 }, + { "label": "24\"", "diameter_mm": 540 }, + { "label": "24\" Schwinn", "diameter_mm": 540 }, + { "label": "26\"", "diameter_mm": 559 }, + { "label": "650c", "diameter_mm": 571 }, + { "label": "650b", "diameter_mm": 584 }, + { "label": "27.5", "diameter_mm": 584 }, + { "label": "26 x 1 1/2\"", "diameter_mm": 584 }, + { "label": "650a", "diameter_mm": 590 }, + { "label": "26 x 1 3/8\"", "diameter_mm": 590 }, + { "label": "650", "diameter_mm": 597 }, + { "label": "26 x 1 1/4\"", "diameter_mm": 597 }, + { "label": "29er", "diameter_mm": 622 }, + { "label": "700c", "diameter_mm": 622 }, + { "label": "27 inch", "diameter_mm": 630 } + ], + "tire_sizes": [ + { "label": "18C", "diameter_mm": 18 }, + { "label": "19C", "diameter_mm": 19 }, + { "label": "20C", "diameter_mm": 20 }, + { "label": "21C", "diameter_mm": 21 }, + { "label": "23C", "diameter_mm": 23 }, + { "label": "25C", "diameter_mm": 25 }, + { "label": "26C", "diameter_mm": 26 }, + { "label": "28C", "diameter_mm": 28 }, + { "label": "30C", "diameter_mm": 30 }, + { "label": "32C", "diameter_mm": 32 }, + { "label": "35C", "diameter_mm": 35 }, + { "label": "38C", "diameter_mm": 38 }, + { "label": "40C", "diameter_mm": 40 }, + { "label": "44C", "diameter_mm": 44 }, + { "label": "50C", "diameter_mm": 50 }, + { "label": "56C", "diameter_mm": 56 }, + { "label": "1.00 inch", "diameter_mm": 25.4 }, + { "label": "1 1/8 inch", "diameter_mm": 28.575 }, + { "label": "1.25 inch", "diameter_mm": 31.75 }, + { "label": "1 3/8 inch", "diameter_mm": 34.925 }, + { "label": "1.4 inch", "diameter_mm": 35.56 }, + { "label": "1.5 inch", "diameter_mm": 38.1 }, + { "label": "1.75 inch", "diameter_mm": 44.45 }, + { "label": "1.95 inch", "diameter_mm": 49.5 }, + { "label": "2.00 inch", "diameter_mm": 50.8 }, + { "label": "2.10 inch", "diameter_mm": 53.34 }, + { "label": "2.125 inch", "diameter_mm": 54 }, + { "label": "2.20 inch", "diameter_mm": 55.88 }, + { "label": "2.25 inch", "diameter_mm": 57.15 }, + { "label": "2.30 inch", "diameter_mm": 58.42 }, + { "label": "2.35 inch", "diameter_mm": 59.69 }, + { "label": "2.40 inch", "diameter_mm": 60.69 }, + { "label": "2.50 inch", "diameter_mm": 63.5 }, + { "label": "2.60 inch", "diameter_mm": 66.04 }, + { "label": "2.70 inch", "diameter_mm": 68.58 }, + { "label": "2.80 inch", "diameter_mm": 71.12 }, + { "label": "2.90 inch", "diameter_mm": 73.66 }, + { "label": "3.0 inch", "diameter_mm": 76.2 }, + { "label": "3.1 inch", "diameter_mm": 78.74 }, + { "label": "3.2 inch", "diameter_mm": 81.28 }, + { "label": "3.3 inch", "diameter_mm": 83.82 }, + { "label": "3.4 inch", "diameter_mm": 86.36 }, + { "label": "3.5 inch", "diameter_mm": 88.9 }, + { "label": "3.6 inch", "diameter_mm": 91.44 }, + { "label": "3.7 inch", "diameter_mm": 93.98 }, + { "label": "3.8 inch", "diameter_mm": 96.52 }, + { "label": "3.9 inch", "diameter_mm": 99.06 }, + { "label": "4.0 inch", "diameter_mm": 101.6 } + ] +} + +```` + + +Created file `src/types.ts` + +````ts +/** + * Type definitions for the tire size data used throughout the app. + * Each size entry has a human-readable label and a diameter in millimeters. + */ + +/** A single rim or tire size option from our reference data. */ +export interface SizeOption { + label: string; + diameter_mm: number; +} + +/** The shape of the imported tire_sizes.json file. */ +export interface TireSizeData { + wheel_sizes: SizeOption[]; + tire_sizes: SizeOption[]; +} + +/** + * Results from the circumference calculation. + * All values derived from: circumference = 3.13772 * (2 * tire + rim) + */ +export interface CircumferenceResult { + mm: number; + cm: number; + inches: number; + mph_setting: number; +} + +```` + + +Created file `src/utils/calculate_circumference.ts` + +````ts +/** + * calculate_circumference.ts + * + * Pure function that computes the bicycle wheel circumference from rim and + * tire diameters (both in mm). The formula uses 3.13772 instead of exact π + * to approximate the "roll-out" circumference (tire compressed under rider + * weight). + * + * Formula: circumference_mm = 3.13772 × (2 × tire_diameter + rim_diameter) + */ + +import type { CircumferenceResult } from "../types"; + +/** The modified Pi constant that accounts for tire compression. */ +const ROLLOUT_PI = 3.13772; + +/** + * Returns circumference in multiple units, or null when inputs are invalid + * (non-positive or missing). + */ +export function calculate_circumference( + rim_mm: number, + tire_mm: number, +): CircumferenceResult | null { + if (rim_mm <= 0 || tire_mm <= 0 || isNaN(rim_mm) || isNaN(tire_mm)) { + return null; + } + + const circ_mm = ROLLOUT_PI * (2 * tire_mm + rim_mm); + + return { + mm: Math.round(circ_mm), + cm: Math.round(circ_mm / 10), + inches: Math.round((10 * circ_mm) / 25.4) / 10, + mph_setting: Math.round(circ_mm / 1.6), + }; +} + +```` + + +Now create the main component with the two dropdowns, text inputs, and result output: + +Created file `src/components/SizeSelector.tsx` + +````tsx +/** + * SizeSelector.tsx + * + * A reusable pair of <select> + <input> for choosing a rim or tire size. + * + * Behaviour: + * - Selecting a dropdown option fills the text input with its diameter_mm. + * - Typing a number in the text input auto-selects the first matching + * dropdown option, or falls back to "Custom" if no match exists. + * - Choosing "Custom" in the dropdown does nothing to the text input. + */ + +import type { SizeOption } from "../types"; + +/** Sentinel value used as the <option> value for "Custom". */ +const CUSTOM_VALUE = "__custom__"; + +interface SizeSelectorProps { + /** Human-readable label shown above the controls. */ + label: string; + /** The list of predefined size options to populate the dropdown. */ + options: SizeOption[]; + /** Currently selected dropdown value (a label string or CUSTOM_VALUE). */ + selected_option: string; + /** Current numeric value in the text input (as a string so we can allow empty). */ + input_value: string; + /** Called when the dropdown selection changes. */ + on_option_change: (option_value: string) => void; + /** Called when the text input value changes. */ + on_input_change: (value: string) => void; +} + +export default function SizeSelector({ + label, + options, + selected_option, + input_value, + on_option_change, + on_input_change, +}: SizeSelectorProps) { + return ( + <fieldset className="fieldset"> + <legend className="fieldset-legend">{label}</legend> + + {/* Dropdown for predefined sizes */} + <select + className="select select-bordered w-full" + value={selected_option} + aria-label={`${label} preset`} + onChange={(e) => on_option_change(e.target.value)} + > + <option disabled value=""> + Pick a size + </option> + {options.map((opt, idx) => ( + <option key={`${opt.label}-${idx}`} value={opt.label}> + {opt.label} ({opt.diameter_mm} mm) + </option> + ))} + <option value={CUSTOM_VALUE}>Custom</option> + </select> + + {/* Numeric text input — mirrors / overrides the dropdown */} + <label className="input w-full mt-2"> + <input + type="number" + step="any" + min="0" + className="grow" + placeholder="mm" + value={input_value} + aria-label={`${label} diameter in mm`} + onChange={(e) => on_input_change(e.target.value)} + /> + <span className="label">mm</span> + </label> + </fieldset> + ); +} + +export { CUSTOM_VALUE }; + +```` + + +Created file `src/components/ResultDisplay.tsx` + +````tsx +/** + * ResultDisplay.tsx + * + * Shows the computed circumference in several units inside a styled card. + * When inputs are incomplete / invalid the component shows a helpful prompt. + */ + +import type { CircumferenceResult } from "../types"; + +interface ResultDisplayProps { + result: CircumferenceResult | null; +} + +export default function ResultDisplay({ result }: ResultDisplayProps) { + if (!result) { + return ( + <div className="card card-border bg-base-200"> + <div className="card-body items-center text-center"> + <p className="text-base-content/60"> + Select or enter both rim and tire sizes to see the circumference. + </p> + </div> + </div> + ); + } + + /** Helper to render a single stat inside the stats bar. */ + const stat_item = (title: string, value: string | number, desc: string) => ( + <div className="stat" key={title}> + <div className="stat-title">{title}</div> + <div className="stat-value text-lg">{value}</div> + <div className="stat-desc">{desc}</div> + </div> + ); + + return ( + <div className="card card-border bg-base-200"> + <div className="card-body"> + <h2 className="card-title justify-center">Wheel Circumference</h2> + <div className="stats stats-vertical sm:stats-horizontal shadow w-full"> + {stat_item("Millimeters", result.mm, "mm")} + {stat_item("Centimeters", result.cm, "cm")} + {stat_item("Inches", result.inches, "in")} + {stat_item("MPH Setting", result.mph_setting, "speedometer")} + </div> + </div> + </div> + ); +} + +```` + + +Now the main App component that wires everything together: + +Failed creating `src/App.tsx` - File already exists + + +Edited `src/App.tsx` file +Replace entire App.tsx with the tire calculator app + + +Wait, I had an issue with the emoji encoding. Let me fix that: + +Edited `src/App.tsx` buffer +Fix the bicycle emoji - use literal emoji instead of escape sequence + + +Now clean up the CSS — remove all the custom Vite boilerplate styles: + +Edited `src/index.css` file +Strip all custom CSS from index.css, keep only Tailwind + daisyUI imports + + +Delete files we no longer need: + +Deleted file `src/App.css` + + +Deleted file `src/assets/react.svg` + + +Now let me verify the final state of all new/changed files: + +Read file `src/App.tsx` (0 - end) + + +Let me also check that `tsconfig.app.json` supports `resolveJsonModule` for the JSON import: + +Read file `tsconfig.app.json` (0 - end) + + +The `moduleResolution: "bundler"` handles JSON imports fine with Vite. `resolveJsonModule` is implicitly true with this setup. Good. + +Now let me verify all the files look correct: + +Read file `src/components/SizeSelector.tsx` (0 - end) + + +Read file `src/components/ResultDisplay.tsx` (0 - end) + + +Let me do a final check on all the changes: + +Reading changed files + + +Everything looks clean. Here's a summary of what was built: + +### Files created +| File | Purpose | +|---|---| +| `src/data/tire_sizes.json` | Reference data for rim and tire sizes (copied from your JSON) | +| `src/types.ts` | TypeScript interfaces for `SizeOption`, `TireSizeData`, `CircumferenceResult` | +| `src/utils/calculate_circumference.ts` | Pure function using the roll-out formula: `3.13772 × (2t + r)` | +| `src/components/SizeSelector.tsx` | Reusable dropdown + numeric input pair with bidirectional sync | +| `src/components/ResultDisplay.tsx` | Shows circumference in mm, cm, inches, and MPH setting using daisyUI stats | + +### Files modified +| File | Change | +|---|---| +| `src/App.tsx` | Replaced Vite boilerplate with the calculator wiring two `SizeSelector`s and a `ResultDisplay` | +| `src/index.css` | Stripped custom CSS, kept only `@import "tailwindcss"` + `@plugin "daisyui"` | + +### Files deleted +| File | Reason | +|---|---| +| `src/App.css` | No longer needed — all styling via utility classes | +| `src/assets/react.svg` | Boilerplate asset no longer referenced | + +### Key behaviours +- **Dropdown → input:** Selecting an option fills the text input with its `diameter_mm` +- **Input → dropdown:** Typing a number auto-matches the first option with that exact `diameter_mm`, or selects "Custom" if no match +- **Custom selected:** Choosing "Custom" from the dropdown does nothing to the text input +- **Results:** Computed live via `useMemo` whenever either input changes — shows mm, cm, inches, and MPH setting + +You could try running the dev server next to verify everything renders, and consider adding unit tests for `calculate_circumference` as a good next step. + +## Me + +> Context: +> - <rules>.rules/daisyui.md</rules> +> - <rules>.rules/project.md</rules> +> - <file>reference/tire-sizes.json</file> +> - <file>reference/howto.mdown</file> +> - <group>files</group> + + |
