Hello. I am having trouble writing a query id to a JSON file

Viewed 32

So far I have a Next.js app with a form component that looks like this:

the components/Form.js

import { useState } from 'react'
import { useRouter } from 'next/router'
import { mutate } from 'swr'

const Form = ({ formId, demoForm, forNewDemo = true }) => {
  const router = useRouter()
  const contentType = 'application/json'
  const [errors, setErrors] = useState({})
  const [message, setMessage] = useState('')

  const [form, setForm] = useState({
    projectName: demoForm.projectName,
    projectVariable: demoForm.projectVariable,
  })

  /* The PUT method edits an existing entry in the mongodb database. */
  const putData = async (form) => {
    const { id } = router.query

    try {
      const res = await fetch(`/api/demos/${id}`, {
        method: 'PUT',
        headers: {
          Accept: contentType,
          'Content-Type': contentType,
        },
        body: JSON.stringify(form),
      })

      // Throw error with status code in case Fetch API req failed
      if (!res.ok) {
        throw new Error(res.status)
      }

      const { data } = await res.json()

      mutate(`/api/demos/${id}`, data, false) // Update the local data without a revalidation
      router.push('/')
    } catch (error) {
      setMessage('Failed to update')
    }
  }

  /* The POST method adds a new entry in the mongodb database. */
  const postData = async (form) => {
    try {
      const res = await fetch('/api/demos', {
        method: 'POST',
        headers: {
          Accept: contentType,
          'Content-Type': contentType,
        },
        body: JSON.stringify(form),
      })

      // Throw error with status code in case Fetch API req failed
      if (!res.ok) {
        throw new Error(res.status)
      }

      router.push('/')
    } catch (error) {
      setMessage('')
    }
  }

  const handleChange = (e) => {
    const target = e.target
    const value =
      target.name === 'poddy_trained' ? target.checked : target.value
    const name = target.name

    setForm({
      ...form,
      [name]: value,
    })
  }

  /* Makes sure demo info is filled for demo name, owner name, species, and image url*/
  const formValidate = () => {
    let err = {}
    if (!form.projectVariable) err.projectVariable = 'Function is required'
    return err
  }

  const handleSubmit = (e) => {
    e.preventDefault()
    const errs = formValidate()
    if (Object.keys(errs).length === 0) {
      forNewDemo ? postData(form) : putData(form)
    } else {
      setErrors({ errs })
    }
  }

  return (
    <>
      <form id={formId} onSubmit={handleSubmit}>
        <textarea
          name="projectVariable"
          value={form.projectVariable}
          onChange={handleChange}
        />
        <input
          name="projectName"
          value={form.projectName}
          onChange={handleChange}
        />
        <button type="submit" className="btn">
          Submit
        </button>
      </form>
      <div>
        {Object.keys(errors).map((err, index) => (
          <li key={index}>{err}</li>
        ))}
      </div>
    </>
  )
}

export default Form

the form is located at the /new page

pages/new.js

import Form from '../components/Form'

const New = () => {
  const demoForm = {
    projectVariable: [],
    projectName: []
  }

  return <Form formId="add-demo-form" demoForm={demoForm} />
}

export default New

and here is my api at pages/api/demos/index.js

import dbConnect from '../../../lib/dbConnect';
import Demo from '../../../models/Demo';
import fs from 'fs';

export default async function handler(req, res) {
  const {
    query: { id },
    method,
  } = req
  await dbConnect()

  switch (method) {
    case 'POST':
      try {
        const timestamp = (JSON.parse(JSON.stringify(new Date())));
        const newJsonDirectory = "projects/";
        const newJsonFile = newJsonDirectory + timestamp + ".json";
        const activeUser = process.env.ACTIVE_USERNAME;
        const newFileName = req.body.projectName;
        fs.writeFileSync(newJsonFile, JSON.stringify(
          {
            "order": [
                {
                    "username": activeUser,
                    "pages": [
                        {
                            "display": "projects",
                            "subpages": [
                                {
                                    "route": timestamp,
                                    "display": newFileName
                                }
                            ]
                        }
                    ]
                }
            ]
        }));
        const demo = await Demo.create(
          req.body
        )
        res.status(201).json({ success: true, data: demo })
      } catch (error) {
        res.status(400).json({ success: false })
      }
      break
    default:
      res.status(400).json({ success: false })
      break
  }
}

lets say I submit my values into the form input: projectName

input: hello-world

the projects folder would then contain a file called 2022-09-11T231607.396Z.json that looks like this

{
    "order": [
        {
            "username": "projectmikey",
            "pages": [
                {
                    "display": "projects",
                    "subpages": [
                        {
                            "route": "2022-09-11T23:16:07.396Z",
                            "display": "hello-world"
                        }
                    ]
                }
            ]
        }
    ]
}

The nested format of the JSON object is perfect however I can't seem to get the query id to show up in place of the date in the new file.

I have tried changing the timestamp variable to ${id} or id, among other things within my pages/api/demos/index.js but nothing seems to work.

the changed file

import dbConnect from '../../../lib/dbConnect';
import Demo from '../../../models/Demo';
import fs from 'fs';

export default async function handler(req, res) {
  const {
    query: { id },
    method,
  } = req
  await dbConnect()

  switch (method) {
    case 'POST':
      try {
        const timestamp = (JSON.parse(JSON.stringify(new Date())));
        const newJsonDirectory = "projects/";
        const newJsonFile = newJsonDirectory + id + ".json";
        const activeUser = process.env.ACTIVE_USERNAME;
        const newFileName = req.body.projectName;
        fs.writeFileSync(newJsonFile, JSON.stringify(
          {
            "order": [
                {
                    "username": activeUser,
                    "pages": [
                        {
                            "display": "projects",
                            "subpages": [
                                {
                                    "route": id,
                                    "display": newFileName
                                }
                            ]
                        }
                    ]
                }
            ]
        }));
        const demo = await Demo.create(
          req.body
        )
        res.status(201).json({ success: true, data: demo })
      } catch (error) {
        res.status(400).json({ success: false })
      }
      break
    default:
      res.status(400).json({ success: false })
      break
  }
}

the file name shows up as undefined.json within the projects/ directory and the new contents looks are:

{
    "order": [
        {
            "username": "projectmikey",
            "pages": [
                {
                    "display": "projects",
                    "subpages": [
                        {
                            "display": "hello-world"
                        }
                    ]
                }
            ]
        }
    ]
}

I am relatively new to Node.js and have been banging my head around on this one

I am also wondering how to append to new JSON file rather that creating a new file upon each request...

If anyone could help me out with either of those 2 questions it would be greatly appreciated! Thanks y'all

0 Answers
Related