+
-
{re.name}
+
{re.name}
@@ -40,11 +40,9 @@ const ingredients = await Promise.all(
-
diff --git a/src/pages/recipe/new.astro b/src/pages/recipe/new.astro
new file mode 100644
index 0000000..605314b
--- /dev/null
+++ b/src/pages/recipe/new.astro
@@ -0,0 +1,94 @@
+---
+import SiteLayout from "@/layouts/base";
+
+const { recipeid } = Astro.params;
+
+// Actually post the recipe with the stored variables
+async function submitRecipe() {
+
+}
+
+---
+
+
+
+
+
+
+
+
+
+
+
Steps
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/script/newRecipe.ts b/src/script/newRecipe.ts
new file mode 100644
index 0000000..ae08d43
--- /dev/null
+++ b/src/script/newRecipe.ts
@@ -0,0 +1,185 @@
+let ingredientFields: HTMLInputElement[] = []
+let ingredientTable: HTMLTableSectionElement = document.querySelector('#ingredient-table')!
+let ingredientAddButton: HTMLButtonElement = document.querySelector('#add-ingredient-btn')!
+
+let stepInput: HTMLTextAreaElement = document.querySelector('#new-instruction')!
+let stepAddButton: HTMLButtonElement = document.querySelector('#add-step-btn')!
+let stepList: HTMLUListElement = document.querySelector('#step-list')!
+let currentStepIndex = 0
+
+// - VARS
+let ingredients: {qty: string, unit: string, name: string}[] = []
+let steps: {
+ index: number,
+ instruction: string,
+ ingredients: string[], // IDs of ingredient fields
+}[] = []
+
+// - INIT
+document.addEventListener('DOMContentLoaded', function() {
+
+ ingredientFields.push(
+ document.querySelector('#ing-qty')!,
+ document.querySelector('#ing-unit')!,
+ document.querySelector('#ing-name')!
+ )
+
+ stepInput.addEventListener('input', showAddStepButton)
+
+ // show plus button once the user types in the text fields
+ ingredientFields.forEach(f => {
+ f.addEventListener('input', showAddIngredientButton)
+ f.addEventListener('keydown', showAddIngredientButton)
+ })
+ // onclick for add button
+ document.querySelector('#add-ingredient-btn')?.addEventListener('click', addIngredient);
+
+ // Enter key navigation for ingredient fields
+ ingredientFields[0].addEventListener('keydown', e => {
+ if (e.key === 'Enter') {
+ ingredientFields[1].focus() // Move from qty to unit
+ }
+ })
+
+ ingredientFields[1].addEventListener('keydown', e => {
+ if (e.key === 'Enter') {
+ ingredientFields[2].focus() // Move from unit to name
+ }
+ })
+
+ // for pressing enter to add ingredient (on the last field)
+ ingredientFields[2].addEventListener('keydown', e => {if (e.key === 'Enter') addIngredient()} )
+
+ // Initial check for button state
+ showAddIngredientButton()
+ showAddStepButton()
+
+ // Steps
+ stepInput.addEventListener('keyup', e => { if (e.key === 'Enter' && e.shiftKey) addStep() } )
+ stepAddButton.addEventListener('click', addStep)
+});
+
+// - ADD
+function addIngredient() {
+ const ing = {
+ qty: ingredientFields[0].value,
+ unit: ingredientFields[1].value,
+ name: ingredientFields[2].value
+ }
+
+ ingredients.push(ing)
+
+ const newRow = document.createElement('tr')
+ newRow.innerHTML = `
+
${ing.qty} |
+
${ing.unit} |
+
${ing.name} |
+ `
+
+ // Add row to table and clear fields
+ ingredientTable.appendChild(newRow)
+ ingredientFields.forEach(f => f.value = '')
+ ingredientAddButton.disabled = true // Hide Add Ingredient button
+ // move cursor to Qty field again
+ ingredientFields[0].focus()
+}
+
+function addStep() {
+ const step = {
+ index: currentStepIndex++,
+ instruction: stepInput.value,
+ ingredients: []
+ }
+
+ steps.push(step)
+ renderSteps()
+ stepInput.value = ''
+ stepAddButton.disabled = true
+ stepInput.focus()
+}
+
+function renderSteps() {
+ // clear the step list
+ stepList.innerHTML = ''
+
+ // re-render all steps in their current order
+ steps.forEach((step, displayIndex) => {
+ const newStep = document.createElement('div')
+ // times like this i regret using astro
+ newStep.innerHTML = `
+
+
+
Step ${displayIndex + 1}
+
+
+
+
+
+
+
+
+
+ `
+ newStep.id = `step-${step.index}`
+ newStep.className = "bg-[#2a2b2c] rounded-lg mb-2 p-3"
+ stepList.appendChild(newStep)
+ })
+
+ // event listeners to reorder buttons
+ document.querySelectorAll('#move-up-btn').forEach(btn => {
+ btn.addEventListener('click', (e) => {
+ const stepIndex = parseInt((e.target as HTMLButtonElement).dataset.stepIndex!)
+ moveStep(stepIndex, -1)
+ })
+ })
+
+ document.querySelectorAll('#move-down-btn').forEach(btn => {
+ btn.addEventListener('click', (e) => {
+ const stepIndex = parseInt((e.target as HTMLButtonElement).dataset.stepIndex!)
+ moveStep(stepIndex, 1)
+ })
+ })
+}
+
+// - UTILS
+function showAddIngredientButton() {
+ const hasQty = ingredientFields[0].value.trim().length > 0
+ const hasName = ingredientFields[2].value.trim().length > 0
+
+ if (hasQty && hasName) {
+ ingredientAddButton.disabled = false
+ } else {
+ ingredientAddButton.disabled = true
+ }
+}
+
+function showAddStepButton() {
+ if (stepInput.value.trim().length > 0) {
+ stepAddButton.disabled = false
+ } else {
+ stepAddButton.disabled = true
+ }
+}
+
+// shift: the direction to move. should be +1 to move down or -1 to move up the list
+function moveStep(stepIndex: number, shift: number) {
+ // Find the step in the array
+ const currentStepArrayIndex = steps.findIndex(step => step.index === stepIndex)
+
+ if (currentStepArrayIndex === -1) return // step not found
+
+ const newIndex = currentStepArrayIndex + shift
+
+ // check bounds
+ if (newIndex < 0 || newIndex >= steps.length) return
+
+ // swap the steps in the array
+ const temp = steps[currentStepArrayIndex]
+ steps[currentStepArrayIndex] = steps[newIndex]
+ steps[newIndex] = temp
+
+ // re-render the steps
+ renderSteps()
+}
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
index ccf6cb5..a95a021 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -7,6 +7,7 @@
"paths": {
"@/components/*": ["src/components/*.astro"],
"@/layouts/*": ["src/layouts/*.astro"],
+ "@/script/*": ["src/script/*"],
"@/utils": ["src/utils/index.ts"],
"@/data/*": ["src/data/*"],
"@/site-config": ["src/site.config.ts"]