How to use Tailwind in a Chrome extensions?

As many of you know Chrome extensions are just regular javascript/css/html files.
Since there is no tailwind.min.css file and there is no npm in a Vanilla chrome extensions this leads me to the question:

How does one use Tailwind in an existing chrome extensions?

Please note that migrating the entire extension to some React template that finally builds into an extension is not a reasonable solution to just include tailwind styles.

Different ways of passing a variable by reference?

I want to pass a variable to a function and have the function change the value.

I know I can do this as an object but am wondering if there is some way to do this that I haven’t thought of.

This is what I want to do, but it doesn’t work the way I want of course:

function test1(vari) {
    vari = 2;
}
var myvar1 = 1;
test1(myvar1);
console.log(myvar1);

This works, but I don’t really want to make all the variables objects:

function test2(vari) {
    vari.val = 2;
}
var myvar2 = { val: 1 };
test2(myvar2);
console.log(myvar2.val);

This also works, but not an acceptable solution:

function test3(vari) {
    eval(vari + ' = 2;');
}
var myvar3 = 1;
test3('myvar3');
console.log(myvar3);

Is there a better option than these?

I cannot get my custom js module classes to export

Context:
Typescript,
custom module with target environment react

source code: https://github.com/bingomanatee/wonderlandlabs-monorepo/tree/main/packages/forestry

continually getting “exports is not defined”

tried setting moudle/target in TSconfig:

{
  "compilerOptions": {    "target": "ESNext",
    "module": "ESNext",    "declaration": true,    "outDir": "./lib",    "downlevelIteration": true,    "isolatedModules": false,    "strict": false,    "moduleResolution": "node",                "types": [
      "jest",
      "node",
      "@types/jest"
    ],     "esModuleInterop": true,    "resolveJsonModule": true,
    "skipLibCheck": true,  },
  "include": [
    "src",
  ],
  "exclude": [
    "node_modules",
    "__tests__
    "lib
    "lib
  ],
  "rules": {
    "@typescript-eslint/ban-ts-comment": false
  }
}

what am I missing?

How do I properly download files and save to a zip in javascript from presigned urls coming from AWS S3?

I have an AWS S3 bucket with open permissions that look like this:

**[
{
    "AllowedHeaders": [
        "*"
    ],
    "AllowedMethods": [
        "GET",
        "PUT",
        "POST",
        "DELETE",
        "HEAD"
    ],
    "AllowedOrigins": [
        "*"
    ],
    "ExposeHeaders": [
        "ETag"
    ],
    "MaxAgeSeconds": 3000
}**

I also have a IAM user/policy that looks like this:

**{
"Version": "2012-10-17",
"Statement": [
    {
        "Sid": "AllowAllOrigins",
        "Action": [
            "s3:*"
        ],
        "Effect": "Allow",
        "Resource": [
            "arn:aws:s3:::my-bucket/*",
        ]
    },
    {
        "Effect": "Allow",
        "Action": [
            "s3:ListBucket",
            "s3:GetObject",
            "s3:PutObject",
            "s3:DeleteObject"
        ],
        "Resource": [
            "arn:aws:s3:::my-bucket/*",
        ]
    }
]

}**

I am struggline with an error related to CORS: http://localhost:3000 has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I upload my files via a pre-signed url, and also get my files with a pre-signed url. The issue is when I try and download them I get a CORS error most of the time. Rarely it will go through and let me download my files.

Here is the code that I am using to download the files:

    const handleDownload = async () => {
        const zip = new JSZip();

    // Fetch each file and add it to the zip
    for (const item of selectedItems) {
        // item is the index and fileItems[item] is the pre-signed url
        const response = await fetch(fileItems[item].url);
        const blob = await response.blob();
        const splitUrl = fileItems[item].url.split('?');
        const fileNameFromUrl = splitUrl[0].split('/');
        const filename = fileNameFromUrl[7];
        zip.file(filename, blob);
    }

    // Generate the zip file and trigger download
    zip.generateAsync({ type: 'blob' }).then((content) => {
        saveAs(content, 'selected-files.zip');
    });
};

I’ve tried pretty much everything to get the files to download without issue, every time.
Anyone know how I can remove this CORS roadblock?

Get 422 error when trying to connect frontend to server

I am using fastapi-users library for authentication and authorization. Everything worked properly in swagger but when I am trying to connect backend and frontend i get such an error and such data:
[HTTP/1.1 422 Unprocessable Entity 8ms]

request: {"username":"[email protected]","password":"me"}
response: {"detail":[{"type":"missing","loc":["body","username"],"msg":"Field required","input":null},{"type":"missing","loc":["body","password"],"msg":"Field required","input":null}]}

I added CORS and MiddleWare, so it should be ok there.

origins = [
        f"http://{FRONT_HOST}:{FRONT_PORT}",
    ]
app.add_middleware(
        CORSMiddleware,
        allow_origins=origins,
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )

Here is my Login code:

import React, { useState } from 'react';

const Login = () => {
  const [formData, setFormData] = useState({
        username: '',
        password: '',
    });


  const [error, setError] = useState('');
  const [success, setSuccess] = useState('');

  const handleChange = (e) => {
        const { name, value } = e.target;
        setFormData({
            ...formData,
            [name]: value,
        });
  };

  const handleSubmit = async (e) => {
    e.preventDefault();

    try {
        const response = await fetch('http://localhost:8000/auth/jwt/login', {
            method: "POST",
            headers: {
                'accept': 'application/json',
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: JSON.stringify({
                username: formData.username,
                password: formData.password})
        });

        if (!response.ok) {
            throw new Error('Error during registration');
        }

        const data = await response.json();
        setSuccess('Login successful!');
        return <Redirect to='/account' />;
        // Возможно, вам нужно будет перенаправить пользователя или обновить состояние приложения


    } catch (err) {
        setError(err.message);
    }
  };

  return (
    <form onSubmit={handleSubmit} style={{ maxWidth: '400px', margin: 'auto' }}>
      <h2>Login</h2>
        <div>
          <label>Email:</label>
          <input
            type="email"
            name="username"
            value={formData.username}
            onChange={handleChange}
            required
          />
        </div>
        <div>
          <label>Password:</label>
          <input
            type="password"
            name="password"
            value={formData.password}
            onChange={handleChange}
            required
          />
        </div>
        <button type="submit">Enter</button>
    </form>
  );
}

export default Login;

I read the github code of OAuth2PasswordRequestForm but still cannot understand what is the root of this problem.

I’ve tried different variations of:

  • body parameter in fetch (JSON.stringify, and just formData)
  • tried to add other optional parameters (grant_type, scope, client_id, client_secret)
  • tried to use both “application/x-www-form-urlencoded” and “application/json” content types

Maybe I do not understand how forms and JSON are sent.
I think there is a problem in sending data.
I would be glad to find out how it should actually work because I am new to making fullstack.

Unexpected domcontentloaded and load event firing playwright [closed]

page.waitForLoadState: Timeout 30000ms exceeded. =========================== logs =========================== "domcontentloaded" event fired "load" event fired ==============================

Keep getting above error while running test cases even though i don’t have any explicit waitForLoadstate for domcontentloaded or load.

Please help me find the better solution

Need a smooth navigation

How to reliably record input texts on each keystroke?

Here is a simple web page which stores unique input texts as Map keys. This is triggered the keyup event on the text input field. In case a particular text already exists in the Map, a message “repeat” is displayed in the label with id = ‘old’. This works as expected when I type slowly but it usually displays “repeat” when I type quickly, even for first time texts. How can I fix this?

class KeyupClass {
  newlabel = document.getElementById('new');

  textmap = new Map();

  oldlabel = document.getElementById('old');

  update = (event) => {
    this.newlabel.innerHTML = `new text ${event.target.value}`;
    if (this.textmap.has(event.target.value)) this.oldlabel.innerHTML = 'repeat';
    else {
      this.textmap.set(event.target.value, this.oldlabel.innerHTML);
      this.oldlabel.innerHTML = `previous text ${event.target.value}`;
    }
  };

  constructor() {
    document.getElementById('textinput').addEventListener('keyup', this.update);
  }
}
new KeyupClass();
<!doctype html>
<html lang="en-US">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>keyup event test</title>
</head>

<body>
  <div style="display: grid">
    <label>editing input updates old and new labels on each keystroke</label>
    <input type="text" id="textinput" placeholder="add text here" />
    <label id="old">old text</label>
    <label id="new">new text</label>
  </div>
</body>

</html>

Uploading video to blogger from NodeJS

I am trying to upload video to blogger using following code. I am able to get the response from my code. I am getting stuck at, that I am not able to transfer the video data to blogger.

My NodeJS code:

const axios = require('axios');
const fs = require('fs');
const path = require('path');

const videoPath = '/Downloads/11H3Bepq6Hx_seEhq2iO7OSW1zC01PnKo.mp4';
const videoStream = fs.createReadStream(videoPath);

let data = '{"protocolVersion":"0.8","createSessionRequest":{"fields":[{"external":{"name":"file","filename":"11H3Bepq6Hx_seEhq2iO7OSW1zC01PnKo.mp4","put":{},"size":1018020}},{"inlined":{"name":"title","content":"11H3Bepq6Hx_seEhq2iO7OSW1zC01PnKo.mp4","contentType":"text/plain"}},{"inlined":{"name":"addtime","content":"1726417159033","contentType":"text/plain"}},{"inlined":{"name":"onepick_version","content":"v2","contentType":"text/plain"}},{"inlined":{"name":"onepick_host_id","content":"10","contentType":"text/plain"}},{"inlined":{"name":"onepick_host_usecase","content":"RichEditor","contentType":"text/plain"}},{"inlined":{"name":"tos","content":"true","contentType":"text/plain"}},{"inlined":{"name":"blogID","content":"add-your-own-id-here","contentType":"text/plain"}},{"inlined":{"name":"postID","content":"add-your-own-id-here","contentType":"text/plain"}}]}}';

let config = {
    method: 'post',
    url: 'https://docs.google.com/upload/blogger/resumable?authuser=0&opi=98421741',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
        'Accept': '*/*',
        'Sec-Fetch-Site': 'same-origin',
        'Accept-Language': 'en-IN,en-GB;q=0.9,en;q=0.8',
        'Accept-Encoding': 'gzip, deflate, br',
        'Sec-Fetch-Mode': 'cors',
        'Host': 'docs.google.com',
        'Origin': 'https://docs.google.com',
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6 Safari/605.1.15',
        'Referer': 'https://docs.google.com/',
        'Content-Length': '860',
        'Connection': 'keep-alive',
        'Sec-Fetch-Dest': 'empty',
        'Cookie': '',
        'X-Goog-Upload-Header-Content-Type': 'video/mp4',
        'X-Goog-Upload-Header-Content-Length': '1018020',
        'X-Client-Pctx': 'CgcSBWjtl_cu',
        'X-Goog-Upload-Protocol': 'resumable',
        'X-Goog-Upload-Command': 'start'
    },
    data: data
};

axios.request(config)
    .then((response) => {
        console.log(JSON.stringify(response.data));
        
        const boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW';
        const body = `--${boundary}rn` +
            `Content-Disposition: form-data; name="metadata"rnrn` +
            `${data}rn` +
            `--${boundary}rn` +
            `Content-Disposition: form-data; name="Filedata"; filename="${path.basename(videoPath)}"rn` +
            `Content-Type: video/mp4rn` +
            `Content-Transfer-Encoding: binaryrnrn` +
            `${fs.readFileSync(videoPath, { encoding: 'binary' })}rn` +
            `--${boundary}--`;

        let config = {
            method: 'post',
            url: `https://docs.google.com/upload/blogger/resumable?authuser=0&opi=98421741&upload_id=${response.data['sessionStatus']['upload_id']}&upload_protocol=resumable`,
            headers: {
                'Content-Type': `multipart/related; boundary=${boundary}`,
                'Accept': '*/*',
                'Sec-Fetch-Site': 'same-origin',
                'Accept-Language': 'en-IN,en-GB;q=0.9,en;q=0.8',
                'Accept-Encoding': 'gzip, deflate, br',
                'Sec-Fetch-Mode': 'cors',
                'Host': 'docs.google.com',
                'Origin': 'https://docs.google.com',
                'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6 Safari/605.1.15',
                'Referer': 'https://docs.google.com/',
                'Content-Length': '1018020',
                'Connection': 'keep-alive',
                'Sec-Fetch-Dest': 'empty',
                'Cookie': '',
                "X-Goog-Upload-Protocol": "multipart",
            },
            "cache": "default",
            "credentials": "include",
            "mode": "cors",
            "redirect": "follow",
            "referrer": "https://docs.google.com/",
            "referrerPolicy": "origin",
            data: body
        };

        axios.request(config)
            .then((response) => {
                console.log(JSON.stringify(response.data));
            })
            .catch((error) => {
                console.log(error);
            });
    })
    .catch((error) => {
        console.log(error);
    });

The response I am getting from blogger:

{"sessionStatus":{"state":"FINALIZED","externalFieldTransfers":[{"name":"file","status":"COMPLETED","bytesTransferred":0,"bytesTotal":1018020,"putInfo":{"url":"https://docs.google.com/upload/blogger/resumable?authuser=0&opi=98421741&upload_protocol=resumable&upload_id=AD-8ljsco6WMZdutraflzfW1AtmJ1k5OYO2PudwjgaYof8PaCSqRn5kqZofxDnlNtVlaig95-jM&file_id=000"},"content_type":"video/mp4"}],"additionalInfo":{"uploader_service.GoogleRupioAdditionalInfo":{"completionInfo":{"status":"SUCCESS"}}},"upload_id":"AD-8ljsco6WMZdutraflzfW1AtmJ1k5OYO2PudwjgaYof8PaCSqRn5kqZofxDnlNtVlaig95-jM"}}

You see the bytesTransferred shows 0. It means video data is not transferred.

When tranferring through browser, response generated is as follows:

{"sessionStatus":{"state":"FINALIZED","externalFieldTransfers":[{"name":"file","status":"COMPLETED","bytesTransferred":1018020,"bytesTotal":1018020,"putInfo":{"url":"https://docs.google.com/upload/blogger/resumable?authuser=0u0026opi=98421741u0026upload_id=AD-8ljvGMD4Mg6k6oSxW74UCa0gsZKJt3grXpwNS6UFtbCnu0D-HyPXF5_B_Krr1aJ-mZQjJ3jcicPLGUSAARAl4TJdDosvQiwltu-Xd139T0aI0u0026file_id=000"},"content_type":"video/mp4"}],"additionalInfo":{"uploader_service.GoogleRupioAdditionalInfo":{"completionInfo":{"status":"SUCCESS","customerSpecificInfo":{"contentId": "ed34314396d57090"}}}},"upload_id":"AD-8ljvGMD4Mg6k6oSxW74UCa0gsZKJt3grXpwNS6UFtbCnu0D-HyPXF5_B_Krr1aJ-mZQjJ3jcicPLGUSAARAl4TJdDosvQiwltu-Xd139T0aI0"}}

Here bytesTransferred is 1018020 same as bytesTotal.

Upon more research, I came across this code:

h.Xc = function() {
        var a = yd(this.Ca);
        this.V.length != null && (a["Content-Length"] = this.V.length);
        a = fac(a);
        a["X-Goog-Upload-Protocol"] = "multipart";
        a["Content-Type"] = "multipart/related; boundary=" + this.U;
        this.H = "Transferring";
        this.N = new DZ;
        this.O.te();
        this.O.listen(this.N, "progress", this.pda);
        this.O.listen(this.N, "complete", this.oda);
        var b = this.N,
            c = b.send,
            d = this.Ia,
            e = this.Ha,
            f = "--" + this.U + 'rnContent-Disposition: form-data; name="metadata"rnrn' + (this.Ga + "rn--") + this.U + 'rnContent-Disposition: form-data; name="Filedata"rnContent-Transfer-Encoding: ' +
            (this.La + "rnrn") + this.V + "rn--" + this.U + "--rn";
        this.wa = f.length - this.V.length;
        c.call(b, d, e, f, a)
    };

But still the error is there. In my code, to simulate please login in blogger. Grab cookie value. Also replace add-your-own-id-here in data variable with appropriate values.

Thank You

Cannot access JavaScript Modules from Cloudflare R2…Why am I getting CORS Errors?

I am using R2 to serve static files for my webpage index.html:


    <script type="module" src="{% static 'js/display.js' %}"></script>
    <script type="module" src="{% static 'js/run-model.js' %}"></script>    
    <script src="{% static 'js/file.js' %}"></script>

display.js

import { variable1, function1} from "./run-model.js";

run-model.js

import { variable2, function2} from "./display.js";

The site is able to load the js files, but then in addition it throws CORS errors for the modules as they try to import variables. I have tried adding a rule in Cloudflare to set an Access-Control-Allow-Origin header to * and also set a CORS policy on the bucket for anything from my domain https://www.example.com. Still the same issue… Why is this?

Access to script at ‘https://<>.r2.cloudflarestorage.com/bucket/js/display.js’ from origin ‘https://www.example.com’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

GET https://<>.r2.cloudflarestorage.com/bucket/js/display.js net::ERR_FAILED 400 (Bad Request)

Access to script at ‘https://<>.r2.cloudflarestorage.com/bucket/js/run-model.js’ from origin ‘https://www.example.com’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

GET https://<>.r2.cloudflarestorage.com/bucket/js/run-model.js net::ERR_FAILED 400 (Bad Request)

The two failed items don’t have the Access-Control-Allow-Origin header and have the Content-Type header as ‘application/xml’:

enter image description here

How to add thresholds with specific ranges to a Highcharts graph?

I’m working on a Highcharts line chart where I need to add thresholds with specific ranges on the x-axis. I want certain areas of the chart to be colored based on these thresholds, Here are the details of my problem:
I’ve used the zone configuration options in Highcharts to try to implement this, but I’m not getting the desired results. Here’s the code I’ve used so far:

Thresholds:

Threshold 1:
    Value: 10°C
    Range: from 100 meters to 500 meters (on the x-axis)

Threshold 2:
    Value: 20°C
    Range: from 600 meters to 2682 meters (on the x-axis)

I want to:

Color the area between 100 meters and 500 meters red if the temperature is above 10°C.
Color the area between 600 meters and 2682 meters red if the temperature is above 20°C.
Display dashed lines at the thresholds of 10°C and 20°C.




  Highcharts.chart('container', {
  title: {
    text: 'Thermal Profile'
  },
  series: [
    {
      name: 'Temperature 0-10°C',
      data: [
        [0, 20.18], [1, 20.21], [2, 20.38], /* ... */ [99, 19.95] // Data filtered for temperatures below 10°C
      ],
      color: '#83c081', // Color for temperatures < 10°C
      zones: [
        {
          value: 10,
          color: '#83c081'
        }
      ]
    },
    {
      name: 'Temperature 10-20°C',
      data: [
        [100, 10.5], [101, 11.2], /* ... */ [499, 19.8] // Data filtered for temperatures between 10°C and 20°C
      ],
      color: '#dc0059', // Color for temperatures > 10°C and < 20°C
      zones: [
        {
          value: 20,
          color: '#dc0059'
        }
      ]
    },
    {
      name: 'Temperature 20-30°C',
      data: [
        [600, 21.5], [601, 22.0], /* ... */ [2682, 27.5] // Data filtered for temperatures between 20°C and 30°C
      ],
      color: '#83c081', // Color for temperatures > 20°C
      zones: [
        {
          color: '#83c081'
        }
      ]
    }
  ],
  xAxis: {
    title: {
      text: 'Distance (m)'
    },
    categories: ["0", "550", "1100", "1650", "2150", "2682"]
  },
  yAxis: {
    title: {
      text: 'Temperature (°C)'
    },
    plotLines: [
      {
        color: '#dc0059',
        dashStyle: 'Dash',  // Dashed line
        value: 10, // Threshold at 10°C
        width: 2,
        label: {
          text: 'Threshold 10°C',
          align: 'right'
        }
      },
      {
        color: '#dc0059',
        dashStyle: 'Dash',  // Dashed line
        value: 20, // Threshold at 20°C
        width: 2,
        label: {
          text: 'Threshold 20°C',
          align: 'right'
        }
      }
    ]
  },
  tooltip: {
    headerFormat: '<b>{point.x} m</b><br>',
    pointFormat: 'Temperature: {point.y} °C'
  }
});

Trouble making API POST request with Next.js

I am a noob when it comes to anything related to backend, also new in Next.js and TypeScript.
I am trying to make a POST request to an API, which should receive formData and create a new listing based on that formData. I am trying to do this with Next.js server actions and route handlers.

Here is my code:

This is from the form component:

    const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault();

        const form = e.currentTarget as HTMLFormElement;
        const formData = new FormData(form);
        
        const address = formData.get("address");
        const mail = formData.get("mail");
        const region_id = selectedRegion?.id; //these come from states
        const agent_id = selectedAgent?.id;  //these come from states
        const city_id = selectedCity?.id;   //these come from states
        const area = formData.get("area");
        const price = formData.get("price");
        const type = formData.get("type");
        const cover = formData.get("cover"); // This is the file input

        try {
            console.log(address, mail, region_id, agent_id, city_id, area, price, type, cover);

            const newFormData = new FormData();

            newFormData.append("address", address as string);
            newFormData.append("mail", mail as string);
            newFormData.append("region_id", region_id as any);
            newFormData.append("agent_id", agent_id as any);
            newFormData.append("city_id", city_id as any);
            newFormData.append("area", area as string);
            newFormData.append("price", price as string);
            newFormData.append("type", type as string);
            newFormData.append("cover", cover as File); 
            
            await addListingAction(newFormData)
        } catch (error) {
            alert(`Error: ${error}`);
        }
    };

This is my server action:

    export async function addListingAction(formData: FormData) {
  try {
    await addListing(formData);
  } catch (error) {
    console.log(error);
  } finally {
    revalidatePath("/")
  }
}

my api.ts file:

export async function addListing(formData: FormData) {

  return await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/add-listing`, {
    method: 'POST',
    body: formData,
  })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Error:', error));
}

and my route.ts file:

import { NextResponse } from 'next/server';

export async function POST(req: Request) {
  try {
    const formData = await req.formData();

    const address = formData.get("address");
    const mail = formData.get("mail");
    const region_id = formData.get("region_id");
    const agent_id = formData.get("agent_id");
    const city_id = formData.get("city_id");
    const area = formData.get("area");
    const price = formData.get("price");
    const type = formData.get("type");
    const cover = formData.get("cover") as File | null;

    const form = new FormData();
    if (address) form.append("address", address);
    if (mail) form.append("mail", mail);
    if (region_id) form.append("region_id", region_id);
    if (agent_id) form.append("agent_id", agent_id);
    if (city_id) form.append("city_id", city_id);
    if (area) form.append("area", area);
    if (price) form.append("price", price);
    if (type) form.append("type", type);
    if (cover instanceof File) form.append("cover", cover);

    const REDBERRY_API_TOKEN = process.env.REDBERRY_API_TOKEN;

    if (!REDBERRY_API_TOKEN) {
      throw new Error("Missing API token");
    }


    const response = await fetch('https://api.real-estate-manager.redberryinternship.ge/api/real-estates', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${REDBERRY_API_TOKEN}`,
      },
      body: form,
    });


if (!response.ok) {
  let errorResponse;
  try {
    errorResponse = await response.json();
  } catch {
    errorResponse = await response.text();
  }
  console.error('HTTP error! Status:', response.status, 'Response:', errorResponse);
  return NextResponse.json(
    { message: 'API request failed', error: errorResponse },
    { status: response.status }
  );
}


  const listing = await response.json();

  return NextResponse.json({ listing }, { status: 201 });

  } catch (error) {
    const message = error instanceof Error ? error.message : 'An unexpected error occurred';
    console.error('Error creating listing:', message);
  return NextResponse.json(
    { message: 'Failed to create listing', error: message },
    { status: 500 }
  );
  }
}

The API documentation says that the curl request looks like this:

    curl -X 'POST' 
  'https://api.real-estate-manager.redberryinternship.ge/api/real-estates' 
  -H 'accept: application/json' 
  -H 'Authorization: Bearer API_TOKEN' 
  -H 'Content-Type: multipart/form-data' 
  -F 'region_id=1' 
  -F 'price=100000' 
  -F 'zip_code=0101' 
  -F 'area=100.5' 
  -F 'city_id=1' 
  -F 'address=example address' 
  -F 'agent_id=371' 
  -F 'bedrooms=3' 
  -F 'is_rental=0' 
  -F '[email protected];type=image/png' 
  -F 'description=house near metro station'

and the response looks like this:

"price": "100000",
  "zip_code": "0101",
  "area": "100.5",
  "city_id": "1",
  "address": "example description",
  "agent_id": "371",
  "bedrooms": "3",
  "is_rental": "0",
  "description": "house near metro station",
  "image": "https://api.real-estate-manager.redberryinternship.ge/storage/images/vZ6KRjLiBIoVqwl4GMniE598mAzno8wqzCkZyg3f.png",
  "created_at": "2024-09-15T16:43:21.000000Z",
  "id": 450

The error I am getting is:

Error creating listing: Unexpected token ‘<‘, “<!DOCTYPE “… is not valid JSON
POST /api/add-listing 500 in 931ms
{
message: ‘Failed to create listing’,
error: ‘Unexpected token ‘<‘, “<!DOCTYPE “… is not valid JSON’
}

Any help would be greatly appreciated.

Shuffling a list based on specific requirements

I am building an online language experiment using JavaScript. As a beginner-level javaScript learner, I am having difficulties shuffling a list based on specific requirements and sampling items from the shuffled list. I would very much appreciate any help in figuring out how to do this.

I have a list of words as follows. Condition X1 = X2, Y1 = Y2. This is to make things clearer later.

word_number condition word
w1 X1 a
w1 X2 b
w1 Y1 c
w1 Y2 d
w2 X1 e
w2 X2 f
w2 Y1 g
w2 Y2 h
w3 X1 i
w3 X2 j
w3 Y1 k
w3 Y2 l
w4 X1 m
w4 X2 n
w4 Y1 o
w4 Y2 p

First, I would like to shuffle the list so that the four words of the same word_number will stay together. I expect the list to be like this:

word_number condition word
w2 X1 e
w2 X2 f
w2 Y1 g
w2 Y2 h
w4 X1 m
w4 X2 n
w4 Y1 o
w4 Y2 p
w3 X1 i
w3 X2 j
w3 Y1 k
w3 Y2 l
w1 X1 a
w1 X2 b
w1 Y1 c
w1 Y2 d

Second, I would like to shuffle the two words of the same condition in the list. I expect the list to be like this.

word_number condition word
w2 X2 f
w2 X1 e
w2 Y2 h
w2 Y1 g
w4 X1 m
w4 X2 n
w4 Y2 p
w4 Y1 o
w3 X2 j
w3 X1 i
w3 Y1 k
w3 Y2 l
w1 X1 a
w1 X2 b
w1 Y2 d
w1 Y1 c

Lastly, I want to select one word from each word_number, including two from X condition and two from Y condition. So basically, select the first word of word_number 2 and 4 in X condition and the first word of word_number 3 and 1 in Y condition.

word_number condition word
w2 X2 f
w4 X1 m
w3 Y1 k
w1 Y2 d

This final list is what I would like to have for my experiment.

ApexCharts.js brush option enabled error: Uncaught (in promise) ReferenceError: ApexCharts is not defined

I am trying to create a candlestick combo chart per example shown in the ApexCharts example Apex Candlestick Charts

I use Vite, and am importing it from the node_modules folder via:
import ApexCharts from "apexcharts";

and then attempting to render it:

let options = {
    series: [
      {
        data: chartData,
      },
    ],
    chart: {
      type: "candlestick",
      height: 300,
      id: "mainCandle",
      toolbar: {
        autoSelected: "pan",
        show: true,
      },
      zoom: {
        enabled: true,
      },
    },
    tooltip: {
      enabled: false,
    },
    plotOptions: {
      candlestick: {
        colors: {
          upward: "#3C90EB",
          downward: "#DF7D46",
        },
      },
    },
    xaxis: {
      type: "datetime",
    },
  };

  chart = new ApexCharts(document.querySelector("#chart-candlestick"), options);
  chart.render();

  let optionsBar = {
    series: [
      {
        name: "volume",
        data: chartData,
      },
    ],
    chart: {
      height: 150,
      type: "candlestick",
      brush: {
        enabled: true,
        target: "mainCandle",
        autoScaleYaxis: true,
      },
      toolbar: {
        autoSelected: "pan",
        show: true,
      },
      zoom: {
        enabled: true,
      },
      selection: {
        enabled: true,
        xaxis: {
          min: new Date("01 Jul 2024").getTime(),
          max: new Date("04 Sep 2024").getTime(),
        },
        fill: {
          color: "#ccc",
          opacity: 0.4,
        },
        stroke: {
          color: "#0D47A1",
        },
      },
    },
    tooltip: {
      enabled: false,
    },
    dataLabels: {
      enabled: false,
    },
    plotOptions: {
      bar: {
        columnWidth: "80%",
        colors: {
          ranges: [
            {
              from: -1000,
              to: 0,
              color: "#F15B46",
            },
            {
              from: 1,
              to: 10000,
              color: "#FEB019",
            },
          ],
        },
      },
    },
    stroke: {
      width: 0,
    },
    xaxis: {
      type: "datetime",
      axisBorder: {
        offsetX: 13,
      },
    },
    yaxis: {
      labels: {
        show: false,
      },
    },
  };

  chartBar = new ApexCharts(document.querySelector("#chart-bar"), optionsBar);
  chartBar.render();`

The 1st chart renders as expected, but the 2nd chart gives the error: Uncaught (in promise) ReferenceError: ApexCharts is not defined

This only seems to error out if the brush option is turned on like so:

chart: {
  brush: { 
    enabled: true,
    target: "target",
    }
}

Open to suggestions. =)