How to find property in array of object and stop looping

I have an array of objects

const jobs = [
{   "id": 1,
    "title": "Item 1",
    "Invoice Net": "€120.00",
    "Invoice VAT": "€0.00",
    "Invoice Total": "€120.00"
},
{   "id": 2,
    "title": "Item 2",
},
{   "id": 3,
    "title": "Item 1",
    "Invoice Net": "€200.00",
    "Invoice VAT": "€20.00",
    "Invoice Total": "€240.00"
},

];

I want to loop through the array and then through its objects to find the first existing “Invoice Net” key. When the key is found I want to pass its value to the variable and stop looping.

My solution so far is

let passedValue = null;

jobs.forEach((job) => {
  if('Invoice Net' in job){
    passedValue = job['Invoice Net'];
    
}
 break;
})

It’s obviously not working as the break statement is not allowed in forEach loop

I want to create a class that lets me make an API call with only 2 parameters

(The code is in JS)
My function for making an API call right now is:
function makeRequest(section, command, requestParams, method) {}
I also have enums such as:

    enum USER_SECTION {
        SECTION = 'users',
        GET_ALL = 'get-all'
        ...
    }

So when I want to make an API request I do:
makeRequest(USER_SECTION.SECTION, USER_SECTION.GET_ALL, {...}, "GET")

I want to create an enum that works as follows:
makeRequest(USER_SECTION.GET_ALL, requestParams)

Which means that in the makeRequest function I have to get
USER_SECTION.SECTION from USER_SECTION.GET_ALL

My biggest problem is that I dont want to repeat the name of the section in the object for every command. Before I had something like:

    USER_SECTION {
        GET_ALL = {
            section = 'users',
            command_name = 'get-all'
        },
        GET = {
            section = 'users',
            command_name = 'get'
        }
        ...
    }

but I want to avoid having to type section = '...' in every command.
Since I have a separate enum for every section of my API there has to be a way for me to get a field of the class, enum or whatever the command is a field of.

So my questions are:
Is it possible? Is it worthed? Is there a better way?

Thanks in advance.

Javascript-How can I change style of my app in a click and change again in a second click and return to my initial style in third click

I’m making a calculator with Javascript and I want to make a button that if I click on it whole style of my project changes and if I click again whole style changes again and at third click it returns to initial style

I don’t have any Idea how I can change whole style for three times just with one button?

Too many OpenLayers moveend triggers when resizing the window

I’m using OpenLayers inside the React environment (background info). I want to control what the map shows with React – using context and other components. For example, zoom in to the map if something is selected in the react components. I am using the latest OpenLayers (10.1) and React(18.3.1), and the problem I have is that the moveEnd event triggers too many times. For a simple window resize, I’m getting 20+ move-end triggers:

enter image description here

My problem is that I’m trying to load new data for the map, and this triggers too many requests against the backend. So I thought that perhaps Moveend was not the best event, but other similar events, like Dragend, also triggered the same number of events.

I’m also thinking, that perhaps in React environment the way I do things is not the best, as map resizes trigger data (re)loads, but data loads also trigger re-renders.

The image is taken before I simplified my whole setup, but currently it’s like that:

'use client';

import { useRef, useState, useCallback, useContext } from 'react';
import { useQuery } from '@tanstack/react-query';

import { Feature } from 'ol';
import { fromLonLat, toLonLat } from 'ol/proj';
import { getBottomLeft, getTopRight } from 'ol/extent';

import { Point } from 'ol/geom';
import { Icon, Style } from 'ol/style';

import { fetcher } from 'utils/axios';
import { MapContext } from 'context/ResizeableMapContext';
import OSMTileLayer from 'components/atoms/OSMTileLayer';
import MapComponent from 'components/atoms/Map';
import VectorLayer from 'components/atoms/VectorLayer';

const AuthenticatedMap = function () {
    const { mapArea, mapObject, setMapObject } = useContext(MapContext);
    const [mapBox, setMapBox] = useState({});

    const onMoveEnd = useCallback((e) => {
        console.log('ON MOVE END TRIGGERS');
        const { map } = e;
        const extent = map.getView().calculateExtent(map.getSize());
        const bottomLeft = toLonLat(getBottomLeft(extent));
        const topRight = toLonLat(getTopRight(extent));
        setMapBox({
            tr: {
                lon: topRight[0],
                lat: topRight[1],
            },
            bl: {
                lon: bottomLeft[0],
                lat: bottomLeft[1],
            },
        });
    }, []);

    const getUrlAndKey = () => {
        const baseUrl = `/api/ships/visible-ships/?`;
        const baseKey = 'k:';
        if ('tr' in mapBox && 'bl' in mapBox) {
            const {
                tr: { lon: trLon, lat: trLat },
                bl: { lon: blLon, lat: blLat },
            } = mapBox;
            return [
                `${baseUrl}min_lon=${blLon}&min_lat=${blLat}&max_lon=${trLon}&max_lat=${trLat}`,
                `${blLon}&${blLat}&${trLon}&${trLat}`,
            ];
        }
        return [baseUrl, baseKey];
    };

    const [url, key] = getUrlAndKey();

    const { isPending, isError, data } = useQuery({
        queryKey: ['publiclyAvailableShips', key],
        refetchInterval: 1000 * 60,
        queryFn: () => fetcher(url),
        enabled: 'tr' in mapBox && 'bl' in mapBox,
    });

    const features = [];
    if (!isPending && !isError && data.length) {
        data.forEach((ship) => {
            const feature = new Feature({
                geometry: new Point(fromLonLat([ship.latest_position.lon, ship.latest_position.lat])),
            });
            feature.setStyle(
                new Style({
                    image: new Icon({
                        src:
                            "data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' " +
                            "width='32' height='32' viewBox='0 0 24 24' fill='%23e5f2fe' stroke='%23000' " +
                            "stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath " +
                            "d='M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7Z'/%3e%3ccircle " +
                            "cx='12' cy='9' r='3'/%3e%3c/svg%3e",
                        className: 'shadow-xl',
                        scale: 1,
                    }),
                }),
            );
            feature.set('name', ship.name);

            features.push(feature);
        });
    }

    return (
        <MapComponent
            zoom={10}
            center={fromLonLat([24.637865, 59.511668])}
            width={mapArea}
            map={mapObject}
            setMap={setMapObject}
            moveEndCallback={onMoveEnd}
        >
            <OSMTileLayer />
            <VectorLayer>{features}</VectorLayer>
        </MapComponent>
    );
};

export default AuthenticatedMap;

Now, my question is, how can I stop excessive move-end triggers? I mean, I move the window size, like 100 pixels, in 1-2 seconds. That should not trigger the callback 20+ times. Is the solution really to implement my own delay that makes sure the callback is only triggered once per 250ms?

Edit: My current solution is to implement a delay in MapComponent, but is that really the best solution here?

            mapObj.on('moveend', (event) => {
                // Clear previous timeout to reset the delay
                if (moveEndTimeoutRef.current) {
                    clearTimeout(moveEndTimeoutRef.current);
                }

                // Set a new timeout to call the moveEndCallback after 100ms
                moveEndTimeoutRef.current = setTimeout(() => {
                    moveEndCallback(event);
                }, 150); // 150ms delay
            });

All the best,
Alan

Warning: Page: Support for defaultProps will be removed from function components in a future major release

Warning: Page: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.

here is my Page.js file

import { Dimensions, Text, View } from 'react-native';
import PropTypes from 'prop-types';
import React from 'react';
import { useTranslation } from 'react-i18next';

const Page = ({
  isLight,
  image,
  title,
  subtitle,
  width,
  height,
  containerStyles,
  imageContainerStyles,
  allowFontScaling,
  titleStyles,
  subTitleStyles,
}) => {
  let titleElement = title;
  const {t} = useTranslation()
  if (typeof title === 'string' || title instanceof String) {
    titleElement = (
      <View style={styles.padding}>
        <Text allowFontScaling={allowFontScaling} style={[styles.title, isLight ? styles.titleLight : {}, titleStyles]}>
          {title}
        </Text>
      </View>
    );
  }

  let subtitleElement = subtitle;
  if (typeof subtitle === 'string' || subtitle instanceof String) {
    subtitleElement = (
      <View style={styles.padding}>
        <Text allowFontScaling={allowFontScaling} style={[styles.subtitle, isLight ? styles.subtitleLight : {}, subTitleStyles]}>
          {t(subtitle)}
        </Text>
      </View>
    );
  }

  return (
    <View style={[styles.container, containerStyles, { width, height }]}>
      <View style={[styles.imageContainer, imageContainerStyles]}>{image}</View>
      {titleElement}
      {subtitleElement}
    </View>
  );
};

Page.propTypes = {
  isLight: PropTypes.bool.isRequired,
  image: PropTypes.element.isRequired,
  containerStyles: PropTypes.shape({
    style: PropTypes.any,
  }),
  imageContainerStyles: PropTypes.shape({
    style: PropTypes.any,
  }),
  title: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired,
  subtitle: PropTypes.oneOfType([PropTypes.string, PropTypes.element])
    .isRequired,
  allowFontScaling: PropTypes.bool,
  titleStyles: PropTypes.shape({
    style: PropTypes.any,
  }),
  subTitleStyles: PropTypes.shape({
    style: PropTypes.any,
  }),
  width: PropTypes.number.isRequired,
  height: PropTypes.number.isRequired,
};

Page.defaultProps = {
  containerStyles: null,
  imageContainerStyles: null,
  allowFontScaling: true,
  titleStyles: null,
  subTitleStyles: null,
};

const { width, height } = Dimensions.get('window');
const potrait = height > width;

const styles = {
  container: {
    flex: 1,
    flexDirection: 'column',
    alignItems: 'center',
   // justifyContent: potrait ? 'center' : 'flex-start',
    paddingTop: potrait ? 0 : 10,
  },
  imageContainer: {
    flex: 0,
    paddingBottom: potrait ? 60 : 10,
    alignItems: 'center',
    width: '100%',
  },
  padding: {
    paddingHorizontal: 10,
  },
  title: {
    textAlign: 'center',
    fontSize: 26,
    color: '#fff',
    paddingBottom: 15,
  },
  titleLight: {
    color: '#000',
  },
  subtitle: {
    textAlign: 'center',
    fontSize: 16,
    color: 'rgba(255, 255, 255, 0.7)',
  },
  subtitleLight: {
    color: 'rgba(0, 0, 0, 0.7)',
  },
};

export default Page;

package.json file

"react": "18.3.1",
    "react-i18next": "^15.0.1",
    "react-native": "0.75.1",

React / ShadcnUi Switching tabs in react destroys the tab content

I’m developing a React application with a tabbed interface where users can edit program parameters. The data is not saved to the database until the user explicitly clicks the “Save Changes” button. I am using a custom edit mode to allow users to make changes in the frontend.

Problem:

When users switch between tabs and return to a tab where they have made edits, the changes are not reflected, and the original data is displayed instead of the updated data.

ParameterPage Component:

import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { useFetchProgramParametersData } from '@/api/querys';
import ProgramParameters from '@/components/ProgramSpecialParametersTab/ProgramParameters';
import SpecialParameters from '@/components/ProgramSpecialParametersTab/SpecialParameters';
import { useAppDispatch, useAppSelector } from '@/Hooks/hooks';
import { toggleEditMode } from '@/features/EditMode/editModeSlice';

const ParameterPage = () => {
  let { ProgramID } = useParams();
  const dispatch = useAppDispatch();
  const { isEditModeActiv } = useAppSelector((state) => state.editModeState);
  const { data, isError, isLoading } = useFetchProgramParametersData(ProgramID as string);
  const [editableData, setEditableData] = useState<any>(data?.programData);

  useEffect(() => {
    if (data?.programData) {
      setEditableData(data.programData);
    }
  }, [data]);

  const handleToggleEditMode = (event: any) => {
    const buttonType = (event.currentTarget as HTMLButtonElement).dataset
      .buttonType;

    if (isEditModeActiv) {
      if (buttonType === 'discardChanges') {
        // Handle discard changes
      } else if (buttonType === 'saveChanges') {
        // Handle save changes
      }
    }

    dispatch(toggleEditMode());
  };

  if (!ProgramID) return <div>Error: ProgramID is required</div>;
  if (isLoading) return <div>Loading...</div>;
  if (isError) return <div>Error loading data</div>;

  return (
    <div>
      <Tabs defaultValue='Overview'>
        <TabsList>
          <TabsTrigger value='Overview'>Overview</TabsTrigger>
          <TabsTrigger value='ProgramParameters'>Program Parameters</TabsTrigger>
          <TabsTrigger value='SpecialParameters'>Special Parameters</TabsTrigger>
        </TabsList>
        <TabsContent value='Overview'>Overview Content</TabsContent>
        <TabsContent value='ProgramParameters'>
          <ProgramParameters ProgramData={editableData} />
        </TabsContent>
        <TabsContent value='SpecialParameters'>
          <SpecialParameters ProgramData={editableData} />
        </TabsContent>
      </Tabs>
    </div>
  );
};

export default ParameterPage;

ProgramParameter Component:

import { ParameterList } from '@/utils/type'
import { useTranslation } from 'react-i18next'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { Info, Pencil } from 'lucide-react'
import { getRowClassName } from '@/utils/getRowClassName'
import { useAppSelector } from '@/Hooks/hooks'
import { RootState } from '@/store'
import { filterParameters } from './filterParameters'
import { useState } from 'react'
import EditProgramSpecialDailog from './EditProgramSpecialDailog'
import { Button } from '../ui/button'
import { useParams } from 'react-router-dom'

type ProgramParametersProps = {
  ProgramData: ParameterList
}

const ProgramDataTable = ({ ProgramData }: { ProgramData: ParameterList }) => {
  const { t } = useTranslation()
  const { parameters } = useAppSelector(
    (state: RootState) => state.defaultValues
  )
  let { ProgramID } = useParams()

  const [filterdParameters, setFilterdParameters] = useState<ParameterList>(
    filterParameters(ProgramData, parameters, 'PRG', ProgramID as string)
  )
  const [EditDialog, setEditDialog] = useState<boolean>(false)
  const [selectedItem, setSelectedItem] = useState<any>(null)
  const { isEditModeActiv } = useAppSelector(
    (state: RootState) => state.editModeState
  )
  const openEditDialog = (item: any) => {
    setSelectedItem(item)
    setEditDialog(true)
  }

  return (
    <div className='col-span-4 flex flex-col rounded-xl border overflow-auto max-h-[50vh]'>
      <Table className='w-full'>
        <TableHeader className='sticky top-0 bg-popover'>
          <TableRow>
            <TableHead>{t('T_Description')}</TableHead>
            <TableHead>{t('T_Value')}</TableHead>
            <TableHead></TableHead>
          </TableRow>
        </TableHeader>
        <TableBody className='p-0 overflow-scroll'>
          {filterdParameters?.map((item, index) => (
            <TableRow key={index} className={getRowClassName(index)}>
              <TableCell>
                <div className='flex'>
                  <div>{t(`T_${item.ParameterName}`)}</div>
                </div>
              </TableCell>
              <TableCell className=''>
                <div className='flex gap-4'>
                  <div className='flex items-center'>
                    {item.Value ? item.Value : 'N/D'}{' '}
                    {item.Value && item.ParameterUnit}{' '}
                  </div>
                </div>
              </TableCell>
              <TableCell className='p-0'>
                {isEditModeActiv ? (
                  <Button
                    variant='link'
                    onClick={() => {
                      openEditDialog(item)
                    }}
                  >
                    <Pencil size={20} />
                  </Button>
                ) : (
                  <Button variant='link' className=' cursor-default'>
                    <Info size={20} />
                  </Button>
                )}
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
      {EditDialog && (
        <EditProgramSpecialDailog
          EditDialog={EditDialog}
          setEditDialog={setEditDialog}
          selectedItem={selectedItem}
          setFilterdParameters={setFilterdParameters}
        />
      )}
    </div>
  )
}

const ProgramParameters = ({ ProgramData }: ProgramParametersProps) => {
  return (
    <div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-8'>
      <ProgramDataTable ProgramData={ProgramData} />
    </div>
  )
}

export default ProgramParameters

SpecialParameter Component:

import { ParameterList } from '@/utils/type'
import { useTranslation } from 'react-i18next'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { Info, Pencil } from 'lucide-react'
import { getRowClassName } from '@/utils/getRowClassName'
import { filterParameters } from './filterParameters'
import { RootState } from '@/store'
import { useAppSelector } from '@/Hooks/hooks'
import { useState } from 'react'
import EditProgramSpecialDailog from './EditProgramSpecialDailog'
import { Button } from '../ui/button'
import { useParams } from 'react-router-dom'

type SpecialParametersProps = {
  ProgramData: ParameterList
}

const SpecialDataTabel = ({ ProgramData }: { ProgramData: ParameterList }) => {
  const { t } = useTranslation()
  const { parameters } = useAppSelector(
    (state: RootState) => state.defaultValues
  )
  let { ProgramID } = useParams()

  const [filterdParameters, setFilterdParameters] = useState<ParameterList>(
    filterParameters(ProgramData, parameters, 'Special', ProgramID as string)
  )
  const [EditDialog, setEditDialog] = useState<boolean>(false)
  const [selectedItem, setSelectedItem] = useState<any>(null)
  const { isEditModeActiv } = useAppSelector(
    (state: RootState) => state.editModeState
  )
  const openEditDialog = (item: any) => {
    setSelectedItem(item)
    setEditDialog(true)
  }
  return (
    <div className='col-span-4 flex flex-col rounded-xl border overflow-auto max-h-[50vh]'>
      <Table className='w-full'>
        <TableHeader className='sticky top-0 bg-popover'>
          <TableRow>
            <TableHead>{t('T_Description')}</TableHead>
            <TableHead>{t('T_Value')}</TableHead>
            <TableHead></TableHead>
          </TableRow>
        </TableHeader>
        <TableBody className='p-0 overflow-scroll'>
          {filterdParameters.map((item, index) => (
            <TableRow key={index} className={getRowClassName(index)}>
              <TableCell>
                <div className='flex'>
                  <div>{t(`T_${item.ParameterName}`)}</div>
                </div>
              </TableCell>
              <TableCell className=''>
                <div className='flex gap-4'>
                  <div className='flex items-center'>
                    {item.Value ? item.Value : 'N/D'}{' '}
                    {item.Value && item.ParameterUnit}{' '}
                  </div>
                </div>
              </TableCell>
              <TableCell className='p-0'>
                {isEditModeActiv ? (
                  <Button
                    variant='link'
                    onClick={() => {
                      openEditDialog(item)
                    }}
                  >
                    <Pencil size={20} />
                  </Button>
                ) : (
                  <Button variant='link' className=' cursor-default '>
                    <Info size={20} />
                  </Button>
                )}
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
      {EditDialog && (
        <EditProgramSpecialDailog
          EditDialog={EditDialog}
          setEditDialog={setEditDialog}
          selectedItem={selectedItem}
          setFilterdParameters={setFilterdParameters}
        />
      )}
    </div>
  )
}

const SpecialParameters = ({ ProgramData }: SpecialParametersProps) => {
  return (
    <div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-8'>
      <SpecialDataTabel ProgramData={ProgramData} />
    </div>
  )
}

export default SpecialParameters

How can I ensure that changes made in edit mode are preserved and correctly reflected when switching tabs?

Are there any common patterns or best practices for handling such scenarios in React with tabbed interfaces and edit modes?
Thank you for any help or suggestions!

Blog slider does not appear when changing pages React Javascript

This is my page
This is my home page.
When I refresh the page, it loads without any problems and the loading status changes from ‘idle’ to success and I can view the blogs without any problems.

this is same page

However, when switching between pages, the visibility of blogs disappears.

this is same page2

`import React, { useEffect } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { Link } from 'react-router-dom'
import { fetchBlogs } from '../store/blogSlice';

export default function ArticlesBlog() {


    const bloglar = useSelector((state) => state.blog.blogs); // useSelector'ı bileşenin en üstünde çağırın
    const blogdurum = useSelector((state) => state.blog.status);
    const dispatch = useDispatch();

    useEffect(() => {
        // Eğer bloglar boşsa veya `status` loading ise fetch yap
        if (bloglar.length === 0 || blogdurum === 'loading') {
            dispatch(fetchBlogs());
        }
    }, [dispatch, bloglar, blogdurum]);

    return (
        <>
            <section className="no-col-padding">
                <div className="container-fluid">
                    <div className="content_container">
                        <div className="columns_wrap">
                            <div className="column_container column-1_1">
                                <div className="column-inner">
                                    <div className="m_wrapper">
                                        <div className="sc_blogger layout_classNameic_3 template_masonry margin_top_small  sc_blogger_horizontal no_description sc_home-margin-type-h">
                                            <h3 className="sc_blogger_title sc_item_title sc_item_title_without_descr">Blogdan Makaleler</h3>
                                            <h6 className="sc_blogger_subtitle sc_item_subtitle">Blog</h6>
                                            <div className="isotope_wrap" data-columns="3">
                                                {blogdurum === 'loading' && <p>Loading...</p>}
                                                {blogdurum === 'failed' && <p>Error fetching blogs</p>}
                                                {blogdurum === 'ok' && (
                                                    <ul>
                                                        {bloglar.map((item) => (
                                                            <div key={item.id} className="isotope_item isotope_item_classNameic isotope_item_classNameic_3 isotope_column_3">
                                                                <div className="post_item post_item_classNameic post_item_classNameic_3 post_format_standard odd">
                                                                    <div className="post_featured">
                                                                        <div className="post_thumb" data-image={item.img} data-title={item.mindesc}>
                                                                            <Link to={'blog/' + item.slug}>
                                                                                <a className="hover_icon hover_icon_link" href="#">
                                                                                    <img className="post-image" alt={item.mindesc} src={item.img} />
                                                                                </a>
                                                                            </Link>
                                                                        </div>
                                                                    </div>
                                                                    <div className="post_content isotope_item_content">
                                                                        <div className="post_info">
                                                                            <span className="post_info_item post_info_posted">
                                                                                <a href="blog-standart-post.html" className="post_info_date">{item.date}</a>
                                                                            </span>
                                                                        </div>
                                                                        <h5 className="post_title">
                                                                            <a href="blog-standart-post.html">{item.mindesc}</a>
                                                                        </h5>
                                                                        <div className="post-info-bottom">
                                                                            <div className="post_info">
                                                                                <span className="post_info_item post_info_posted_by">By <a href="#" className="post_info_author">{item.author}</a></span>
                                                                                <span className="post_info_item post_info_counters">
                                                                                    <a className="post_counters_item post_counters_comments" title="Comments - 3" href="#">
                                                                                        <span className="post_counters_number">{item.commentcount} yorum</span>
                                                                                    </a>
                                                                                </span>
                                                                            </div>
                                                                        </div>
                                                                        <div className="post_descr">
                                                                            <p></p>
                                                                        </div>
                                                                    </div>
                                                                </div>
                                                            </div>
                                                        ))}
                                                    </ul>
                                                )}

                                            </div>
                                            <div className="sc_blogger_button sc_item_button"><Link to='/blogs'><a href="blog-masonry-3-columns.html" className="sc_button sc_button_square sc_button_style_filled sc_button_size_medium">Daha Fazla</a></Link></div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </section>
        </>
    )
}
`

App.jsx

``import React from 'react';
import { Routes, Route, useLocation } from "react-router-dom";
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import Footer from "./Components/Footer";
import Header from "./Components/Header";
import AboutUs from "./Pages/AboutUsPage";
import BlogsAll from "./Pages/BlogsAll";
import ContactPage from "./Pages/ContactPage";
import Main from "./Pages/Main";
import OurServices from "./Pages/OurServices";
import OurTeam from "./Pages/OurTeam";
import Portfolio from "./Pages/Portfolio";
import Shop from "./Pages/Shop";
import BlogDetail from './Pages/BlogDetail';
import ScrollToTop from './Components/ScrollToUp';

function App() {
  const location = useLocation();

  return (
    <>
      <Header />
      <ScrollToTop/>
      <TransitionGroup>
     
        <CSSTransition
          key={location.key}
          classNames="fade"
          timeout={300}
        >
          <Routes location={location}>
            <Route path="/" element={<Main />} />
            <Route path="/about-us" element={<AboutUs />} />
            <Route path="/blogs" element={<BlogsAll />} />
            <Route path="/blog/:id" element={<BlogDetail />} />
            <Route path="/contact" element={<ContactPage />} />
            <Route path="/our-services" element={<OurServices />} />
            <Route path="/our-team" element={<OurTeam />} />
            <Route path="/portfolio" element={<Portfolio />} />
            <Route path="/shop" element={<Shop />} />
            <Route path="*" element={<Main />} />
          </Routes>
        </CSSTransition>
      </TransitionGroup>
      <Footer />
    </>
  );
}

export default App;
`
`

I tried change useEffect but it not success

Prosemirror Track changes formatting need to track

Hi I am using text editor as prosemirror I am trying to track changes like word I am using prosemirror-changset for tracking the changes,I can able to track the text changes only I am trying try style,Marks also, They issue is When try meger the old changes to new changes , I need merge the old set with new one

Any Help Thanks

/* eslint-disable */

import { Node as PMNode } from "prosemirror-model"
import { AddMarkStep, RemoveMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepMap } from "prosemirror-transform"

import { computeDiff } from "./diff"
import { Change, BlockChange, Span, merge } from './change'

import { IChange } from './change/types'

interface ChangeSetConfig {
  doc: PMNode
  combine: (data1: any, data2: any) => null | any
}

// ::- A change set tracks the changes to a document from a given
// point in the past. It condenses a number of step maps down to a
// flat sequence of replacements, and simplifies replacments that
// partially undo themselves by comparing their content.
export class ChangeSet {

  config: ChangeSetConfig
  changes: IChange[]

  constructor(config: ChangeSetConfig, changes: IChange[]) {
    this.config = config
    // :: [Change] Replaced regions.
    this.changes = changes
  }

  // :: (Node, [StepMap], union<[any], any>) → ChangeSet
  // Computes a new changeset by adding the given step maps and
  // metadata (either as an array, per-map, or as a single value to be
  // associated with all maps) to the current set. Will not mutate the
  // old set.
  //
  // Note that due to simplification that happens after each add,
  // incrementally adding steps might create a different final set
  // than adding all those changes at once, since different document
  // tokens might be matched during simplification depending on the
  // boundaries of the current changed ranges.
  addSteps(oldDoc: PMNode, newDoc: PMNode, steps: Step[], data?: any | any[]) {
    // This works by inspecting the position maps for the changes,
    // which indicate what parts of the document were replaced by new
    // content, and the size of that new content. It uses these to
    // build up Change objects.
    //
    // These change objects are put in sets and merged together using
    // Change.merge, giving us the changes created by the new steps.
    // Those changes can then be merged with the existing set of
    // changes.
    //
    // For each change that was touched by the new steps, we recompute
    // a diff to try to minimize the change by dropping matching
    // pieces of the old and new document from the change.
    let stepChanges: IChange[] = []

    // Add spans for new steps.
    for (let i = 0; i < steps.length; i++) {
      const step = steps[i]

      let d = Array.isArray(data) ? data[i] : data
      let off = 0
      if (step instanceof ReplaceStep) {

        step.getMap().forEach((fromA: number, toA: number, fromB: number, toB: number) => {

          const changedText = oldDoc.content.textBetween(fromA, toA) ?? ''

          stepChanges.push(new Change(fromA + off, toA + off, fromB, toB,
            fromA == toA ? Span.none : [new Span(toA - fromA, changedText)],
            fromB == toB ? Span.none : [new Span(toB - fromB, changedText)],

          ))
          off = (toB - fromB) - (toA - fromA)
        })
      } else if (step instanceof ReplaceAroundStep) {
        let insideReplaceAroundStep = false
        let changeId = Math.random().toString()
        let node: PMNode | null | undefined
        // @ts-ignore
        const { slice } = step
        const nodeDeleted = slice.size === 0
        step.getMap().forEach((fromA: number, toA: number, fromB: number, toB: number) => {
          if (!insideReplaceAroundStep) {
            node = nodeDeleted ? oldDoc.nodeAt(fromA) : newDoc.nodeAt(fromB)
            insideReplaceAroundStep = true
            d = { ...d, blockChange: 'start', changeId, nodeType: node?.type.name }
          } else {
            insideReplaceAroundStep = false
            d = { ...d, blockChange: 'end', changeId, nodeType: node?.type.name }
            changeId = Math.random().toString()
          }
          const newtext = oldDoc.content.textBetween(fromA, toA) ?? ''

          const inserted = fromA == toA ? Span.none : [new Span(toA - fromA, newtext)]
          const deleted = fromB == toB ? Span.none : [new Span(toB - fromB, newtext)]

          stepChanges.push(new BlockChange(fromA + off, toA + off, fromB, toB, inserted, deleted, insideReplaceAroundStep))

          off = (toB - fromB) - (toA - fromA)
        })
      } else if (step instanceof AddMarkStep) {
        const { from, to, mark } = step
        const change = new Change(from, to, from, to, Span.none, [new Span(to - from, mark)])
        stepChanges.push(change)
      } else if (step instanceof RemoveMarkStep) {
        const { from, to, mark } = step
        const change = new Change(from, to, from, to, [new Span(to - from, mark)], Span.none)
        stepChanges.push(change)
      } else {
        console.error('Unknown step type! Change not tracked and possibly current changes have become inconsistent', step)
      }
    }
    if (stepChanges.length == 0) return this

    let newChanges = mergeAll(stepChanges, this.config.combine)

    console.log("changes", newChanges)

    let changes = merge(this.changes, newChanges, this.config.combine)


    // Minimize changes when possible
    for (let i = 0; i < changes.length; i++) {
      let change = changes[i]
      if (change.fromA == change.toA || change.fromB == change.toB ||
        // Only look at changes that touch newly added changed ranges
        !newChanges.some(r => r.toB > change.fromB && r.fromB < change.toB)) continue
      let diff = computeDiff(this.config.doc.content, newDoc.content, change)

      // Fast path: If they are completely different, don't do anything
      if (diff.length == 1 && diff[0].fromB == 0 && diff[0].toB == change.toB - change.fromB)
        continue

      if (diff.length == 1) {
        changes[i] = diff[0]
      } else {
        changes.splice(i, 1, ...diff)
        i += diff.length - 1
      }
    }
    return new ChangeSet(this.config, changes)
  }

  // :: Node
  // The starting document of the change set.
  get startDoc() { return this.config.doc }

  // :: (f: (range: Change) → any) → ChangeSet
  // Map the span's data values in the given set through a function
  // and construct a new set with the resulting data.
  map(f: (range: IChange) => any) {
    return new ChangeSet(this.config, this.changes.map(change => {
      let result = f(change)
      return result === change ? change :
        change.create(change.fromA, change.toA, change.fromB, change.toB, change.deleted, change.inserted)
    }))
  }

  // :: (ChangeSet, ?[StepMap]) → ?{from: number, to: number}
  // Compare two changesets and return the range in which they are
  // changed, if any. If the document changed between the maps, pass
  // the maps for the steps that changed it as second argument, and
  // make sure the method is called on the old set and passed the new
  // set. The returned positions will be in new document coordinates.
  changedRange(b: ChangeSet, maps?: StepMap[]) {
    if (b == this) return null
    let touched = maps && touchedRange(maps)
    let moved = touched ? (touched.toB - touched.fromB) - (touched.toA - touched.fromA) : 0
    function map(p: number) {
      return !touched || p <= touched.fromA ? p : p + moved
    }

    let from = touched ? touched.fromB : 2e8, to = touched ? touched.toB : -2e8
    function add(start: number, end = start) {
      from = Math.min(start, from); to = Math.max(end, to)
    }

    let rA = this.changes, rB = b.changes
    for (let iA = 0, iB = 0; iA < rA.length && iB < rB.length;) {
      let rangeA = rA[iA], rangeB = rB[iB]
      if (rangeA && rangeB && sameRanges(rangeA, rangeB, map)) { iA++; iB++ }
      else if (rangeB && (!rangeA || map(rangeA.fromB) >= rangeB.fromB)) { add(rangeB.fromB, rangeB.toB); iB++ }
      else { add(map(rangeA.fromB), map(rangeA.toB)); iA++ }
    }

    return from <= to ? { from, to } : null
  }

  // :: (Node, ?(a: any, b: any) → any) → ChangeSet
  // Create a changeset with the given base object and configuration.
  // The `combine` function is used to compare and combine metadata—it
  // should return null when metadata isn't compatible, and a combined
  // version for a merged range when it is.
  static create(doc: PMNode, combine = (a: any, b: any): any => a === b ? a : null) {
    return new ChangeSet({ combine, doc }, [])
  }
}

// Exported for testing
// @ts-ignore
ChangeSet.computeDiff = computeDiff

// : ([[Change]], (any, any) → any, number, number) → [Change]
// Divide-and-conquer approach to merging a series of ranges.
function mergeAll(
  ranges: IChange[],
  combine: (data1: any, data2: any) => null | any,
  start = 0,
  end = ranges.length
): IChange[] {
  if (end == start + 1) return [ranges[start]]
  let mid = (start + end) >> 1
  return merge(mergeAll(ranges, combine, start, mid),
    mergeAll(ranges, combine, mid, end), combine)
}

function endRange(maps: StepMap[]) {
  let from = 2e8, to = -2e8
  for (let i = 0; i < maps.length; i++) {
    let map = maps[i]
    if (from != 2e8) {
      from = map.map(from, -1)
      to = map.map(to, 1)
    }
    map.forEach((_s, _e, start, end) => {
      from = Math.min(from, start)
      to = Math.max(to, end)
    })
  }
  return from == 2e8 ? null : { from, to }
}

function touchedRange(maps: StepMap[]) {
  let b = endRange(maps)
  if (!b) return null
  let a = endRange(maps.map(m => m.invert()).reverse())
  if (!a) throw Error('endRange was null!')
  return { fromA: a.from, toA: a.to, fromB: b.from, toB: b.to }
}

function sameRanges(a: IChange, b: IChange, map: (pos: number) => number) {
  return map(a.fromB) == b.fromB && map(a.toB) == b.toB &&
    sameSpans(a.deleted, b.deleted) && sameSpans(a.inserted, b.inserted)
}

function sameSpans(a: Span[], b: Span[]) {
  if (a.length != b.length) return false
  for (let i = 0; i < a.length; i++)
    if (a[i].length != b[i].length || a[i].data !== b[i].data) return false
  return true
}
/* eslint-disable */

import { Span } from './span'
import { Change } from './change'
import type { IChange } from './types'

// : ([Change], [Change], (any, any) → any) → [Change]
// This merges two changesets (the end document of x should be the
// start document of y) into a single one spanning the start of x to
// the end of y.
export function merge(x: IChange[], y: IChange[], combine: (a: any, b: any) => any): IChange[] {
  if (x.length == 0) return y
  if (y.length == 0) return x

  let result = []
  // Iterate over both sets in parallel, using the middle coordinate
  // system (B in x, A in y) to synchronize.
  for (let iX = 0, iY = 0, curX: IChange = x[0], curY: IChange = y[0]; ;) {
    if (!curX && !curY) {
      return result
    } else if (curX && (!curY || curX.toB < curY.fromA)) { // curX entirely in front of curY
      let off = iY ? y[iY - 1].toB - y[iY - 1].toA : 0
      result.push(curX.createNewWithOffset(off, true))
      // result.push(off == 0 ? curX :
      //             new Change(curX.fromA, curX.toA, curX.fromB + off, curX.toB + off,
      //                         curX.deleted, curX.inserted))
      // @ts-ignore
      curX = iX++ == x.length ? null : x[iX]
    } else if (curY && (!curX || curY.toA < curX.fromB)) { // curY entirely in front of curX
      let off = iX ? x[iX - 1].toB - x[iX - 1].toA : 0
      result.push(curY.createNewWithOffset(off, false))
      // result.push(off == 0 ? curY :
      //             new Change(curY.fromA - off, curY.toA - off, curY.fromB, curY.toB,
      //                         curY.deleted, curY.inserted))
      // @ts-ignore
      curY = iY++ == y.length ? null : y[iY]
    } else if (curX.isBlockChange() && curY.isBlockChange() || curX.isBlockChange() && curY.isChange()) {
      let off = iY ? y[iY - 1].toB - y[iY - 1].toA : 0
      result.push(curX.createNewWithOffset(off, true))
      off = iX ? x[iX - 1].toB - x[iX - 1].toA : 0
      result.push(curY.createNewWithOffset(off, false))
      // @ts-ignore
      curX = iX++ == x.length ? null : x[iX]
      // @ts-ignore
      curY = iY++ == y.length ? null : y[iY]
      // debugger
    }
    // else if (curX.isChange() && curY.isBlockChange()) {
    //   throw Error('TODO')
    // } 
    else { // Touch, need to merge
      // The rules for merging ranges are that deletions from the
      // old set and insertions from the new are kept. Areas of the
      // middle document covered by a but not by b are insertions
      // from a that need to be added, and areas covered by b but
      // not a are deletions from b that need to be added.
      let pos = Math.min(curX.fromB, curY.fromA)
      let fromA = Math.min(curX.fromA, curY.fromA - (iX ? x[iX - 1].toB - x[iX - 1].toA : 0)), toA = fromA
      let fromB = Math.min(curY.fromB, curX.fromB + (iY ? y[iY - 1].toB - y[iY - 1].toA : 0)), toB = fromB
      let deleted = Span.none, inserted = Span.none

      // Used to prevent appending ins/del range for the same Change twice
      let enteredX = false, enteredY = false

      // Need to have an inner loop since any number of further
      // ranges might be touching this group
      for (; ;) {
        let nextX = !curX ? 2e8 : pos >= curX.fromB ? curX.toB : curX.fromB
        let nextY = !curY ? 2e8 : pos >= curY.fromA ? curY.toA : curY.fromA
        let next = Math.min(nextX, nextY)
        let inX = curX && pos >= curX.fromB, inY = curY && pos >= curY.fromA
        if (!inX && !inY) break
        if (inX && pos == curX.fromB && !enteredX) {
          deleted = Span.join(deleted, curX.deleted, combine)
          toA += curX.lenA
          enteredX = true
        }
        if (inX && !inY) {
          inserted = Span.join(inserted, Span.slice(curX.inserted, pos - curX.fromB, next - curX.fromB), combine)
          toB += next - pos
        }
        if (inY && pos == curY.fromA && !enteredY) {
          inserted = Span.join(inserted, curY.inserted, combine)
          toB += curY.lenB
          enteredY = true
        }
        if (inY && !inX) {
          deleted = Span.join(deleted, Span.slice(curY.deleted, pos - curY.fromA, next - curY.fromA), combine)
          toA += next - pos
        }

        if (inX && next == curX.toB) {
          // @ts-ignore
          curX = iX++ == x.length ? null : x[iX]
          enteredX = false
        }
        if (inY && next == curY.toA) {
          // @ts-ignore
          curY = iY++ == y.length ? null : y[iY]
          enteredY = false
        }
        pos = next
      }
      if (fromA < toA || fromB < toB)
        result.push(new Change(fromA, toA, fromB, toB, deleted, inserted))
    }
  }
}

Mahara website contents not visible in dashboard

Iam using mahara to build a website. I got the source code from official mahara git repository. But when i edit the contents in the dashboard its working but the content blocks are not visible. when i drag the blocks only the contents are visible. What can i do to resolve this.

I have checked for error, i have resolved almost everything. But still i couldnt able to resolve this problem.

I have checked the errors its showing parse error alone

sendjsonrequest() failed: parsererror 
mahara.js?v=9035:387
l   @   jquery.js:3496
fireWith    @   jquery.js:3626
S   @   jquery.js:9788
(anonymous) @   jquery.js:10047
load        
send    @   jquery.js:10066
ajax    @   jquery.js:9682
sendjsonrequest @   mahara.js?v=9035:345
addNewBlock @   views.js?v=9035:515
(anonymous) @   views.js?v=9035:461
s   @   jquery.js:5174
dispatch    @   jquery.js:5429
m.handle    @   jquery.js:5233
trigger @   jquery.js:8715
(anonymous) @   jquery.js:8793
each    @   jquery.js:381
each    @   jquery.js:203
trigger @   jquery.js:8792
closePositionBlockDialog    @   views.js?v=9035:735
(anonymous) @   views.js?v=9035:717
dispatch    @   jquery.js?v=9035:2
y.handle    @   jquery.js?v=9035:2

why when I click the “Gioca di nuovo” button and play another game, it sends 2 times the same score?

‘When I press the “Gioca di nuovo” button to start a new game, my game sends the score to the server twice, resulting in duplicate records. I believe the issue might be in the sendScoreToServer and resetGame functions, as these are responsible for managing the game restart. The sendScoreToServer function is called when the game ends, and resetGame is invoked to reset game parameters and prepare for a new game. How can I modify these functions to ensure that the score is sent to the server only once, and avoid duplicate records in the leaderboard?’


function startGame() {
    gameStarted = true;
    document.getElementById('login-form').style.display = 'none';  // Nascondi il form di login
    document.addEventListener("keydown", moveShip);
    document.addEventListener("keyup", shoot);
    createDaleks();  // Crea i Dalek
    startDalekBulletTimer(); // Avvia il timer per i proiettili dei Dalek
    requestAnimationFrame(update);  // Avvia il ciclo di aggiornamento
}

function update() {
    if (!gameStarted) {
        return;
    }

    // Mostra il punteggio finale
    let finalScore = document.getElementById('final-score');
    finalScore.innerText = `Score: ${score}`;

    // Mostra il messaggio di game over
    if (gameOver) {
        endGame(); // Chiamata al metodo endGame per gestire la fine del gioco
        return; // Interrompe il ciclo di aggiornamento
    }

    // Disegna lo sfondo
    context.drawImage(spaceImg, 0, 0, boardWidth, boardHeight);

    // Disegna la navicella
    context.drawImage(tardisImg, ship.x, ship.y, ship.width, ship.height);

    // Aggiorna e disegna i Dalek
    for (let i = 0; i < daleksArray.length; i++) {
        let dalek = daleksArray[i];
        if (dalek.alive) {
            dalek.x += dalekVelocityX;

            if (dalek.x + dalek.width >= board.width || dalek.x <= 0) {
                dalekVelocityX *= -1;
                dalek.x += dalekVelocityX * 2;

                for (let j = 0; j < daleksArray.length; j++) {
                    daleksArray[j].y += daleksHeight;
                }
            }

            context.drawImage(dalekImg, dalek.x, dalek.y, dalek.width, dalek.height);

            if (dalek.y >= ship.y) {
                gameOver = true;
                document.getElementById('score').innerText = `Score: ${score} (Game Over)`;
            }
        }
    }

    // Gestione dei proiettili dei Dalek
    for (let i = 0; i < dalekBulletArray.length; i++) {
        let bullet = dalekBulletArray[i];
        bullet.y += dalekBulletVelocityY;  // I proiettili dei Dalek si muovono verso il basso
        context.fillStyle = "red";
        context.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);

        // Verifica se il proiettile colpisce la navicella
        if (detectCollision(bullet, ship)) {
            score -= 50;  // Sottrai 50 punti
            bullet.used = true;  // Marca il proiettile come utilizzato
            if (score < 0) {
                score = 0;
                gameOver = true;
            }
            document.getElementById('score').innerText = `Score: ${score} (Game Over)`;
        }
    }

    while (dalekBulletArray.length > 0 && (dalekBulletArray[0].y > board.height || dalekBulletArray[0].used)) {
        dalekBulletArray.shift();
    }

    // Gestione dei proiettili del giocatore
    for (let i = 0; i < bulletArray.length; i++) {
        let bullet = bulletArray[i];
        bullet.y += tardisBulletVelocity;
        context.fillStyle = "white";
        context.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);

        for (let j = 0; j < daleksArray.length; j++) {
            let dalek = daleksArray[j];
            if (!bullet.used && dalek.alive && detectCollision(bullet, dalek)) {
                bullet.used = true;
                dalek.alive = false;
                dalekCount--;
                score += 100;
                context.fillStyle = "red";
                context.fillRect(dalek.x, dalek.y, dalek.width, dalek.height);
            }
        }
    }

    while (bulletArray.length > 0 && (bulletArray[0].used || bulletArray[0].y < 0)) {
        bulletArray.shift();
    }

    if (dalekCount == 0) {
        score += dalekColumns * dalekRows * 100;
        dalekColumns = Math.min(dalekColumns + 1, rows - 4);
        dalekVelocityX += (dalekVelocityX > 0) ? 0.2 : -0.2;
        daleksArray = [];
        bulletArray = [];
        dalekBulletArray = []; // Resetta i proiettili dei Dalek
        createDaleks();
    }

    document.getElementById('score').innerText = `Score: ${score}`;
    requestAnimationFrame(update);
}

function detectCollision(obj1, obj2) {
    return obj1.x < obj2.x + obj2.width &&
           obj1.x + obj1.width > obj2.x &&
           obj1.y < obj2.y + obj2.height &&
           obj1.y + obj1.height > obj2.y;
}

function shoot(e) {
    if (e.code === "Space" && !gameOver) {
        let bullet = {
            x: ship.x + ship.width / 2 - 2,
            y: ship.y,
            width: 4,
            height: 10,
            used: false
        };
        bulletArray.push(bullet);
    }
}

function moveShip(e) {
    if (gameOver) {
        return;
    }

    if (e.code === "ArrowLeft" && ship.x > 0) {
        ship.x -= shipVelocityX;
    } else if (e.code === "ArrowRight" && ship.x < boardWidth - shipWidth) {
        ship.x += shipVelocityX;
    }
}

function createDaleks() {
    daleksArray = [];
    dalekCount = 0;

    for (let i = 0; i < dalekRows; i++) {
        for (let j = 0; j < dalekColumns; j++) {
            daleksArray.push({
                x: dalekX + j * (daleksWidth + tileSize),
                y: dalekY + i * (daleksHeight + tileSize),
                width: daleksWidth,
                height: daleksHeight,
                alive: true
            });
            dalekCount++;
        }
    }
}

let dalekBulletTimerId; 

function startDalekBulletTimer() {
    if (dalekBulletTimerId) return;

    dalekBulletTimerId = setInterval(() => {
        if (gameOver) {
            clearInterval(dalekBulletTimerId); 
            dalekBulletTimerId = null;
            return;
        }

        let aliveDaleks = daleksArray.filter(dalek => dalek.alive);
        if (aliveDaleks.length > 0) {
            let randomDalek = aliveDaleks[Math.floor(Math.random() * aliveDaleks.length)];
            let bullet = {
                x: randomDalek.x + randomDalek.width / 2 - 2,
                y: randomDalek.y + randomDalek.height,
                width: 4,
                height: 10,
                used: false
            };
            dalekBulletArray.push(bullet);
        }
    }, 1000); 
}



function endGame() {
    document.removeEventListener("keydown", moveShip);
    document.removeEventListener("keyup", shoot);

    document.getElementById('game-over-message').style.display = 'block';
    document.getElementById('end-buttons').style.display = 'block';

    let finalScore = document.getElementById('final-score');
    finalScore.innerText = `Final Score: ${score}`;

    // Ferma la musica di sottofondo
    backgroundMusic.pause();
    backgroundMusic.currentTime = 0; // Riavvolgi la musica all'inizio

    // Recupera l'username dal form di login
    let username = document.getElementById('username').value;

    // Invia il punteggio al server
    if (username) {
        sendScoreToServer(username, score);
    }
}

document.getElementById('view-leaderboard').addEventListener('click', function () {
    showLeaderboard();
});

document.getElementById('back-button').addEventListener('click', function () {
    hideLeaderboard();
});

function showLeaderboard() {
    // Nascondi solo il testo di Game Over e il punteggio
    document.getElementById('game-over-text').style.display = 'none';
    document.getElementById('final-score').style.display = 'none';
    document.getElementById('end-buttons').style.display = 'none';
    document.getElementById('game-over-message').style.display = 'none';

    // Mostra il contenitore della classifica
    document.getElementById('leaderboard-container').style.display = 'flex';
    document.getElementById('back-button').style.display = 'block'; // Mostra il bottone "Indietro"

    // Recupera la classifica dal server
    fetch('../php/space.php')
        .then(response => response.json()) // Converti la risposta in JSON
        .then(data => {
            // Costruisci la tabella dinamicamente
            console.log("sei nella generazione tabella" + data);
            let tabella = `
                <table id="classifica">
                    <thead>
                        <tr>
                            <th>Posizione</th>
                            <th>Username</th>
                            <th>Punteggio</th>
                            <th>Data e ora</th>
                        </tr>
                    </thead>
                    <tbody>
                        ${generaRighe(data)}
                    </tbody>
                </table>
            `;

            let tabellaContainer = document.querySelector("#leaderboard-container");
            tabellaContainer.insertAdjacentHTML('beforeend', tabella);
        })
        .catch(error => console.error('Error:', error));
}




document.getElementById('view-leaderboard').addEventListener('click', function () {
    // Rimuovi la tabella esistente (se presente)
    let oldTable = document.querySelector("#leaderboard-container table");
    if (oldTable) {
        oldTable.remove();
    }
    // (Il resto della funzione rimane invariato)
});

document.getElementById('play-again').addEventListener('click', function () {
    resetGame();
    startGame();
});

function sendScoreToServer(username, score) {
    fetch('../php/save_score.php', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({ username: username, score: score })
    })
        .then(response => response.text())
        .then(data => console.log(data))
        .catch(error => console.error('Error:', error));
}

function resetGame() {
    // Nascondi la schermata di Game Over e la classifica
    document.getElementById('game-over-message').style.display = 'none';
    document.getElementById('end-buttons').style.display = 'none';
    document.getElementById('leaderboard-container').style.display = 'none';

    // Resetta i parametri del gioco
    score = 0;
    gameOver = false;
    daleksArray = [];
    bulletArray = [];
    dalekBulletArray = [];

    // Ripristina la navicella alla posizione iniziale
    ship.x = shipX;
    ship.y = shipY;

    dalekColumns = 3;
    dalekVelocityX = 1;
    dalekBulletVelocityY = 10;

    // Ripristina la musica di sottofondo
    backgroundMusic.currentTime = 0; 
    backgroundMusic.play();

    // Rimuovi gli event listeners esistenti per evitare conflitti
    document.removeEventListener("keydown", moveShip);
    document.removeEventListener("keyup", shoot);

    // Pulisci il timer dei proiettili dei Dalek se esiste
    if (dalekBulletTimerId) {
        clearInterval(dalekBulletTimerId);
        dalekBulletTimerId = null;
    }

    // Riavvia gli event listeners per il gioco
    document.addEventListener("keydown", moveShip);
    document.addEventListener("keyup", shoot);

    // Crea nuovi Dalek e avvia il timer dei proiettili dei Dalek
    createDaleks();
    startDalekBulletTimer(); 

    // Avvia il ciclo di aggiornamento
    requestAnimationFrame(update);

}
this is the javascript code.'

How to implicitly infer generic types from interface property value

So, I have this interface for my Express controller handler.

interface Handler<
  Body extends ZodObject,
  Query extends ZodObject,
  Params extends ZodObject,
> {
  path?: string;
  method: "get" | "post" | "put" | "patch" | "delete";
  validators?: {
    body?: Body;
  };
  handler: RequestHandler<z.infer<Body>>;
}

What I want is that the type of Body should be inferred from the object I set at validator.body. Let’s say I set it to z.object({ x: z.string() }), then I want to the req parameter of handler function to have req.body as { x: string }, but I can’t make it happen.

I tried searching for it on Google and even tried GPT and Gemini but none can solve this problem. I just want to know whether this can be done or not, and if yes then how.

Shopware 6 – Filter Criteria Equals ID from Extension

Good day,

I have created an extension for the Customer Entity. Everything works as it should so far. Now, I want to filter customers in a component based on a specific ID in this extension. I can search by any other field, but as soon as I reference an ID field, I get no results.

Works:

criteriaCustomer.addFilter(
    Criteria.equals('customer.extensions.customerExtension.company_id', this.company.name)
);

Doesn’t work:

criteriaCustomer.addFilter(
    Criteria.equals('customer.extensions.customerExtension.id', "18d034570b9e4cca9b1dc761bb8d794d")
);

Searching the Customer Repository by an ID using the same filter works:

criteriaCustomer.addFilter(
    Criteria.equals('id', "18d034570b9e4cca9b1dc761bb8d794d")
);

Field Collection:

return new FieldCollection([
    (new IdField('id', 'id'))->addFlags(new ApiAware(), new Required(), new PrimaryKey()),
    new FkField('customer_id', 'customerId', CustomerDefinition::class),
    (new StringField('betreuer', 'betreuer')),
    (new IdField('company_id', 'company_id'))->addFlags(new ApiAware()),
    (new StringField('company_name', 'company_name')),
    (new BoolField('company_account', 'company_account')),

    new OneToOneAssociationField('customer', 'customer_id', 'id', CustomerDefinition::class, false)
]);

I suspect that the ID is passed as a string, and thus the query is executed as such. Have I made an obvious mistake here? Have I forgotten to declare something for the ID fields?

I am grateful for any help, and I wish you a great weekend in advance!

Button not getting disabled after popup closes in React

I’m trying to implement a functionality wherein after I click a button, a popup should open with some content, and once it is closed, the button should be permanently disabled.

Now, I’ve implemented the same functionality for another button which works fine in the same component using: –

    const fiftyClickHandler = (event) => {
        event.currentTarget.disabled = true;
        setIsFiftyActive(true);
    }

but it just doesn’t work for the other button (ask-the-expert)

import React from 'react'
import OpenAI from "openai";
import Popup from "./Popup";
export default function Helpline({ data, questionNumber, setIsFiftyActive }) {
    //* Open source API key
    const openai = new OpenAI({
        apiKey: process.env.REACT_APP_API_KEY,
        baseURL: process.env.REACT_APP_BASE_URL,
        dangerouslyAllowBrowser: true
    });
    const [PopupModalOpen, setPopupModalOpen] = React.useState(false)
    const [gptData, setGptData] = React.useState([]);
  
    const expertClickHandler = async (event) => {
        //* Constructing object that would have all answer options and questions to be sent to GPT
        let ansOptions = "";
        data[questionNumber - 1].answers.map((item) => {
            return ansOptions += item.text + ",";
        })
        let contentObj = {
            ansOptions,
            question: data[questionNumber - 1].question
        }
        try {
            const completion = await openai.chat.completions.create({
                model: "pai-001",
                messages: [
                    { role: "system", content: "You are an expert in trivia and general knowledge and are an assistant in a quiz show helping users when they are in need" },
                    {
                        role: "user",
                        content: contentObj,
                    },
                ],
            });
            setGptData(completion.choices[0].message.content);
            console.log(gptData);
        } catch (error) {
            setGptData("Null");
            console.log("Error fetching results")
        }
        setPopupModalOpen(true);
        event.currentTarget.disabled = true;
    }

    const fiftyClickHandler = (event) => {
        event.currentTarget.disabled = true;
        setIsFiftyActive(true);
    }
    return (
        PopupModalOpen ?
            <div>
                <Popup PopupModalOpen={PopupModalOpen} setPopupModalOpen={setPopupModalOpen} />
            </div> :
            //* Expert answer state === false meaning modal is not open */
            <div className="helpline">
                <button className="game-btn" id="fifty-fifty" onClick={fiftyClickHandler}>
                    Fifty Fifty
                </button>
                <button className="game-btn" id="ask-the-expert" onClick={expertClickHandler}>
                    Ask the expert
                </button>
            </div>

    )
}

Why is this happening?

There are two ways to solve this ->

  1. Refs: – I’ve tried using it, but it doesn’t work because after closing the modal, the ref’s value is set to null again and the button doesn’t; get disabled.

  2. State: – An obvious solution, but I want to use them when there is no other solution available.