React Redux QUIZ - reactjs

I am trying to make a simple Quiz work with Redux following this example in https://www.codeproject.com/Articles/5130417/Quiz-Application-in-React-Using-Redux . Somehow I think the quizLoad Reducer is not getting the data or isn't even being called correctly.
This is my Reducer:
const QUIZ_LOAD = 'QUIZ_LOAD';
const QUIZ_ANSWER = 'QUIZ_ANSWER';
const QUIZ_SUBMIT = 'QUIZ_SUBMIT';
const PAGER_UPDATE = 'PAGER_UPDATE';
const INITIAL_STATE = {
quiz: {
config: {
'allowBack': false,
'allowReview': false,
'autoMove': true, // if true, it will move to next question automatically when answered.
'duration': 0, // indicates the time in which quiz needs to be completed. 0 means unlimited.
'pageSize': 1,
'requiredAll': false, // indicates if you must answer all the questions before submitting.
'richText': false,
'shuffleQuestions': false,
'shuffleOptions': false,
'showClock': false,
'showPager': true,
'theme': 'none'
},
questions: []
},
mode: 'quiz',
pager: {
index: 0,
size: 1,
count: 1
}
}
export default (state = INITIAL_STATE, action) => {
const { type, payload } = action;
console.log('REDUCERRRRRRRRR')
switch (type) {
case PAGER_UPDATE:
return { ...state, pager: payload, mode: 'quiz' };
case QUIZ_LOAD:
return { ...state, quiz: payload };
case QUIZ_SUBMIT:
return { ...state, mode: payload };
case QUIZ_ANSWER:
return { ...state, quiz: payload };
default:
return state;
}
};
// <<<ACTIONS>>>
export const pagerUpdate = (payload) => {
return {
type: PAGER_UPDATE,
pager: payload,
mode: 'quiz'
};
};
export const quizLoad = (payload) => {
return {
type: QUIZ_LOAD,
quiz: payload
};
};
export const quizSubmit = (payload) => {
return {
type: QUIZ_SUBMIT,
mode: { payload }
};
};
export const quizAnswer = (payload) => {
return {
type: QUIZ_ANSWER,
quiz: { payload }
}
};
This is my component and where I get the error
"Unhandled Rejection (TypeError): Cannot read property 'config' of
undefined eval
C:\Users\Willkommen\Documents\MyPension\REPOs\web-best\src\pages\header\vertragsCheck\index.js:69:6"
import React from "react";
import { connect } from "react-redux";
import Quiz from "./quiz/Quiz";
import {
pagerUpdate,
quizLoad
} from "redux/vertragsCheck/vertragscheckReducer";
import SEOTitle from "components/SEO/seoTitle";
import WavySectionWrapper from "components/Layouts/Containers/wavySectionWrapper/wavySectionWrapper";
import WavyPageTitleWrapper from "components/Sections/WavyPageTitle/WavyPageTitle";
import Button from "components/Button/Button";
import "./vertragsCheckSteps.scss";
const bgMobileImage =
"/images/illustrations/pages/Home/mobile/mobile-phone1.png";
class vertragsCheck extends React.Component {
state = {
// quizes: [
// { id: 'data/myPensionQuiz.json', name: 'VertragsCheck' },
// { id: 'data/myPensionTest.json', name: 'Rente' }
// ],
quizVisible: false,
quizId: "quizApi/quiz.json"
};
pager = {
index: 0,
size: 1,
count: 1
};
componentDidMount() {
this.load(this.state.quizId);
}
load(quizId) {
let url = quizId || this.props.quizId;
fetch(`../${url}`)
.then(res => res.json())
.then(res => {
let quiz = res;
quiz.questions.forEach(q => {
q.options.forEach(o => (o.selected = false));
});
debugger;
console.log("quizCONFIG", this.props.quiz);
quiz.config = Object.assign(this.props.quiz.config || {}, quiz.config);
this.pager.count = quiz.questions.length / this.pager.size;
this.props.onQuizLoad(quiz);
this.props.onPagerUpdate(this.pager);
});
}
// onChange = (e) => {
// this.setState({ quizId: e.target.value });
// this.load(e.target.value);
// }
handleClick = () => {
const { quizVisible } = this.state;
this.setState({ quizVisible: !quizVisible });
};
render() {
const quizVisible = this.state.quizVisible;
if (!quizVisible) {
return (
<WavySectionWrapper vertical>
<SEOTitle page="vertrags-check" />
<WavyPageTitleWrapper>
<div className="flex-container">
<div>
<h1>
Kostenloser <br />
Vertrags-Check
</h1>
<p>
Ist meine bestehender Vertrag zu teuer? <br />
Wie schneidet meine bestehen Altervorsorge ab? <br />
Wir helfen Dir Deine Altervorsorge zu optimieren.
</p>
<Button size="sm" onClick={this.handleClick}>
Jetzt prüfen
</Button>
</div>
<div>
<img src={bgMobileImage} alt="myPension mobile graphic" />
{/* <img
src="/images/background-elements/bg-vertical-section.svg"
/> */}
</div>
</div>
</WavyPageTitleWrapper>
</WavySectionWrapper>
);
} else if (quizVisible) {
return (
<Quiz
quiz={this.state.quiz}
quizId={this.state.quizId}
mode={this.state.mode}
/>
);
}
}
}
const mapStateToProps = state => {
return { ...state.quiz };
};
const mapDispatchToProps = dispatch => ({
onQuizLoad: payload => dispatch({ type: quizLoad, payload }),
onPagerUpdate: payload => dispatch({ type: pagerUpdate, payload })
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(vertragsCheck);
And this is my quiz data in public folder:
{
"id": 1,
"name": "Vertrags-check Quiz",
"description": "Vertrags-check Quiz determines if your actual pension contract is improvable",
"config": {
"showPager": false,
"allowBack": true,
"autoMove": true
},
"questions": [
{
"id": 1010,
"name": "Sind die Effektivkosten höher als 1,5%?",
"questionTypeId": 1,
"options": [
{
"id": 1055,
"questionId": 1010,
"name": "Ja",
"isAnswer": false
},
{
"id": 1056,
"questionId": 1010,
"name": "Nein",
"isAnswer": false
},
{
"id": 1057,
"questionId": 1010,
"name": "Weiß nicht",
"isAnswer": true
}
],
"questionType": {
"id": 1,
"name": "test type",
"isActive": true
}
},
{
"id": 1011,
"name": "Liegt Dein Rentenfaktor unter 27€?",
"questionTypeId": 1,
"options": [
{
"id": 1055,
"questionId": 1010,
"name": "Ja",
"isAnswer": false
},
{
"id": 1056,
"questionId": 1010,
"name": "Nein",
"isAnswer": false
},
{
"id": 1057,
"questionId": 1010,
"name": "Weiß nicht",
"isAnswer": true
}
],
"questionType": {
"id": 1,
"name": "test type",
"isActive": true
}
},
{
"id": 1012,
"name": "Erfolgt die Anlage zu weniger als 80% in Aktien?",
"questionTypeId": 1,
"options": [
{
"id": 1055,
"questionId": 1010,
"name": "Ja",
"isAnswer": false
},
{
"id": 1056,
"questionId": 1010,
"name": "Nein",
"isAnswer": false
},
{
"id": 1057,
"questionId": 1010,
"name": "Weiß nicht",
"isAnswer": true
}
],
"questionType": {
"id": 1,
"name": "test type",
"isActive": true
}
},
{
"id": 1013,
"name": "Ist Deine Rendite geringer als 3% p.A.?",
"questionTypeId": 1,
"options": [
{
"id": 1055,
"questionId": 1010,
"name": "Ja",
"isAnswer": false
},
{
"id": 1056,
"questionId": 1010,
"name": "Nein",
"isAnswer": false
},
{
"id": 1057,
"questionId": 1010,
"name": "Weiß nicht",
"isAnswer": true
}
],
"questionType": {
"id": 1,
"name": "test type",
"isActive": true
}
},
{
"id": 1014,
"name": "Zahlst Du für Flexibilität?",
"questionTypeId": 1,
"options": [
{
"id": 1055,
"questionId": 1010,
"name": "Ja",
"isAnswer": false
},
{
"id": 1056,
"questionId": 1010,
"name": "Nein",
"isAnswer": false
},
{
"id": 1057,
"questionId": 1010,
"name": "Weiß nicht",
"isAnswer": true
}
],
"questionType": {
"id": 1,
"name": "test type",
"isActive": true
}
},
{
"id": 1015,
"name": "Es gibt keine Steuervorteile bei deinem bestehendem Vertrag?",
"questionTypeId": 1,
"options": [
{
"id": 1055,
"questionId": 1010,
"name": "Ja",
"isAnswer": false
},
{
"id": 1056,
"questionId": 1010,
"name": "Nein",
"isAnswer": false
},
{
"id": 1057,
"questionId": 1010,
"name": "Weiß nicht",
"isAnswer": true
}
],
"questionType": {
"id": 1,
"name": "test type",
"isActive": true
}
},
{
"id": 1016,
"name": "Hast Du Deinen Vertrag nach 2005 abgeschlossen?",
"questionTypeId": 1,
"options": [
{
"id": 1055,
"questionId": 1010,
"name": "Ja",
"isAnswer": false
},
{
"id": 1056,
"questionId": 1010,
"name": "Nein",
"isAnswer": false
},
{
"id": 1057,
"questionId": 1010,
"name": "Weiß nicht",
"isAnswer": true
}
],
"questionType": {
"id": 1,
"name": "test type",
"isActive": true
}
}
]
}

There is problem probably here:
const mapStateToProps = state => { return { ...state.quiz } };
You are using object spread operator, which puts/maps content of the state.quiz into your props. Therefore there isn't any quiz in this.props.
Try to map the state.quiz to this.props.quiz this way:
const mapStateToProps = state => { return { quiz: state.quiz } };
You are also mapping actions to props incorrectly, try this:
const mapDispatchToProps = dispatch => ({
onQuizLoad: payload => dispatch(quizLoad(payload)),
onPagerUpdate: payload => dispatch(pagerUpdate(payload))
});

Related

Job Listing Filtering React

I'm having trouble figuring out how to filter this job listing that I found in frontend mentor.
The filtering partially works. For example, if I add HTML and Senior tag, it filters it correctly. But the logic isn't right cause I test it for other tags and the result doesn't come out as expected.
I appreciate any help to get pointed at the right direction.
this is my App.js code
import './App.css';
import axios from 'axios';
import React, {useState,useEffect} from "react";
import Card from "./components/card/Card";
import Header from "./components/header/Header";
import FilterBar from "./components/FilterBar/FilterBar";
function App() {
const [data, setData] = useState([]);
const URL = 'http://localhost:3000/data.json';
const [category, setCategory] = useState([]);
console.log("category is " + category);
useEffect(() => {
axios.get(URL).then((response) => {
setData(response.data);
//console.log(data);
});
}, []);
/*useEffect(() => {
}, []);*/
function addItem(item){
console.log("addItem " + item);
const duplicateItem = category.find((collection) => collection === item);
if(!duplicateItem){
setCategory([...category, item]);
} else {
alert(item + " is already in the list.");
}
}
function removeAllItems(items, counter){
if(counter > 0){
setCategory(items);
} else {
alert("There are no items in the filter bar to remove.");
}
}
return (
<div className="App">
<Header />
{
category.length > 0 ?
<FilterBar removeAllItems={removeAllItems} languages={category} />
:
""
}
{
Object.keys(data).map((item, index) => (
category.length < 1 ?
<Card
key={index}
data_company_name={data[item].company}
data_logo={data[item].logo}
data_new={data[item].new}
data_featured={data[item].featured}
data_position={data[item].position}
data_languages={data[item].languages}
data_level={data[item].level}
data_role={data[item].role}
data_posted_at={data[item].postedAt}
data_contract={data[item].contract}
data_location={data[item].location}
data_tools={data[item].tools}
addItem={addItem}
/>
: category.includes(data[item].level)
|| category.includes(data[item].role)
|| category.every((language) => data[item].languages.includes(language))
|| category.every((tool) => data[item].tools.includes(tool))
?
<Card
key={index}
data_company_name={data[item].company}
data_logo={data[item].logo}
data_new={data[item].new}
data_featured={data[item].featured}
data_position={data[item].position}
data_languages={data[item].languages}
data_level={data[item].level}
data_role={data[item].role}
data_posted_at={data[item].postedAt}
data_contract={data[item].contract}
data_location={data[item].location}
data_tools={data[item].tools}
addItem={addItem}
/>
: ""
))}
</div>
);
}
export default App;
This is the Card.js
import {StyledCard} from './Card.styled';
const Card = ({addItem, data_logo, data_company_name, data_new, data_featured, data_position, data_languages, data_level, data_role, data_contract, data_posted_at, data_location, data_tools}) => {
const data = data_languages.map( (language, index) => {
return <span onClick={() => addItem(language) } key={index} className={`role-tag-${index}`}>{language}</span>;
});
const tools_data = data_tools.map( (tool, index) => {
return <span key={index} onClick={() => addItem(tool) } className={`data-tools`}>{tool}</span>
});
return (
<>
<div className={`card-container`}>
<StyledCard>
<div className={`inside-card-wrapper`}>
<div className={`img`}>
<img src={data_logo} alt=""/>
<div className={`company-tag-wrapper`}>
<span className={`company-name`}>{data_company_name}</span>
{
data_new === true ?
<span className={`job-tag-new`}>NEW!</span>
:
""
}
{
data_featured === true ?
<span className={`job-tag-featured`}>FEATURED</span>
:
""
}
<div className={`role-title`}>
<div><strong>{data_position}</strong></div>
<div className={`role-tags`}>
<span onClick={() => addItem(data_role)} className={`data-role`}>{data_role}</span>
<span onClick={() => addItem(data_level) } className={`data-level`}>{data_level}</span>
{data}
{tools_data}
</div>
</div>
<div className={`job-type-wrapper`}>
<div className={`post`}>
<span>{data_posted_at}</span>
•
<span>{data_contract}</span>
•
<span>{data_location}</span>
</div>
</div>
</div>
</div>
</div>
</StyledCard>
</div>
</>
);
};
export default Card;
This is the FilterBar.js file
import {StyledFilterBar} from "./FilterBar.styled";
const FilterBar = ({removeAllItems, languages}) => {
//console.log("FilterBar.js " + items);
let counter = 0;
const data = languages.map( (item, index) => {
counter = languages.length;
return <div key={index}>{item} </div>
});
return (
<div>
<StyledFilterBar>
<div className={`filter-options`}>
<div className={`left-side`}>
{data}
</div>
<div className={`right-side`}>
<div onClick={() => removeAllItems([], counter) } className={`clear`}>clear</div>
</div>
</div>
</StyledFilterBar>
</div>
);
};
export default FilterBar;
This is the json file that contains the data
[
{
"id": 1,
"company": "Photosnap",
"logo": "./img/photosnap.svg",
"new": true,
"featured": true,
"position": "Senior Frontend Developer",
"role": "Frontend",
"level": "Senior",
"postedAt": "1d ago",
"contract": "Full Time",
"location": "USA Only",
"languages": ["HTML", "CSS", "JavaScript"],
"tools": []
},
{
"id": 2,
"company": "Manage",
"logo": "./img/manage.svg",
"new": true,
"featured": true,
"position": "Fullstack Developer",
"role": "Fullstack",
"level": "Midweight",
"postedAt": "1d ago",
"contract": "Part Time",
"location": "Remote",
"languages": ["Python"],
"tools": ["React"]
},
{
"id": 3,
"company": "Account",
"logo": "./img/account.svg",
"new": true,
"featured": false,
"position": "Junior Frontend Developer",
"role": "Frontend",
"level": "Junior",
"postedAt": "2d ago",
"contract": "Part Time",
"location": "USA Only",
"languages": ["JavaScript"],
"tools": ["React", "Sass"]
},
{
"id": 4,
"company": "MyHome",
"logo": "./img/myhome.svg",
"new": false,
"featured": false,
"position": "Junior Frontend Developer",
"role": "Frontend",
"level": "Junior",
"postedAt": "5d ago",
"contract": "Contract",
"location": "USA Only",
"languages": ["CSS", "JavaScript"],
"tools": []
},
{
"id": 5,
"company": "Loop Studios",
"logo": "./img/loop-studios.svg",
"new": false,
"featured": false,
"position": "Software Engineer",
"role": "Fullstack",
"level": "Midweight",
"postedAt": "1w ago",
"contract": "Full Time",
"location": "Worldwide",
"languages": ["JavaScript"],
"tools": ["Ruby", "Sass"]
},
{
"id": 6,
"company": "FaceIt",
"logo": "./img/faceit.svg",
"new": false,
"featured": false,
"position": "Junior Backend Developer",
"role": "Backend",
"level": "Junior",
"postedAt": "2w ago",
"contract": "Full Time",
"location": "UK Only",
"languages": ["Ruby"],
"tools": ["RoR"]
},
{
"id": 7,
"company": "Shortly",
"logo": "./img/shortly.svg",
"new": false,
"featured": false,
"position": "Junior Developer",
"role": "Frontend",
"level": "Junior",
"postedAt": "2w ago",
"contract": "Full Time",
"location": "Worldwide",
"languages": ["HTML", "JavaScript"],
"tools": ["Sass"]
},
{
"id": 8,
"company": "Insure",
"logo": "./img/insure.svg",
"new": false,
"featured": false,
"position": "Junior Frontend Developer",
"role": "Frontend",
"level": "Junior",
"postedAt": "2w ago",
"contract": "Full Time",
"location": "USA Only",
"languages": ["JavaScript"],
"tools": ["Vue", "Sass"]
},
{
"id": 9,
"company": "Eyecam Co.",
"logo": "./img/eyecam-co.svg",
"new": false,
"featured": false,
"position": "Full Stack Engineer",
"role": "Fullstack",
"level": "Midweight",
"postedAt": "3w ago",
"contract": "Full Time",
"location": "Worldwide",
"languages": ["JavaScript", "Python"],
"tools": ["Django"]
},
{
"id": 10,
"company": "The Air Filter Company",
"logo": "./img/the-air-filter-company.svg",
"new": false,
"featured": false,
"position": "Front-end Dev",
"role": "Frontend",
"level": "Junior",
"postedAt": "1mo ago",
"contract": "Part Time",
"location": "Worldwide",
"languages": ["JavaScript"],
"tools": ["React", "Sass"]
}
]
The problem is that you're combining all your "categories" into a single filter, but each category (language, tool, etc) has a different matching criteria. I think that the matching criteria you want is:
Any match for the job level or the job role
All match for tools and languages
But you can't do this without knowing the type of filter that you've got for each category.
So, there are a few ways you can solve that. One way would be to to separate out your filters by category. You could write a custom hook to do the heavy lifting:
const createEmptyFilter = () => ({
all: new Set(),
language: new Set(),
tool: new Set(),
role: new Set(),
level: new Set()
});
const useFilter = () => {
const [filter, setFilter] = useState(createEmptyFilter);
const handleAddFilter = (type, value) => {
if (!filter[type]) {
alert(`Unknown filter category: '${type}'`);
return;
}
setFilter((prev) => {
const next = { ...prev };
next.all = new Set(prev.all).add(value);
next[type] = new Set(prev[type]).add(value);
return next;
});
};
const handleClearFilter = () => setFilter(createEmptyFilter());
const matchesFilter = (item) => {
const { language, tool, role, level } = filter;
if (level.size && !level.has(item.level)) return false;
if (role.size && !role.has(item.role)) return false;
for (const l of language) {
if (!item.languages.includes(l)) return false;
}
for (const t of tool) {
if (!item.tools.includes(t)) return false;
}
return true;
};
return [
[...filter.all.values()],
handleAddFilter,
handleClearFilter,
matchesFilter
];
};
A couple of things to note:
The 'all' category is just to maintain the order of items that the user adds entries to the filter. You could compose this by combining the values from all the categories, but you'd lose the ordering.
Now that we know which category each filter belongs to, our filtering criteria can be more specific.
With the card, you'd have to add the category when you apply a filter, for example:
<span
onClick={() => onAddFilter("role", data_role)}
className={`data-role`}
>
Here's an updated sample.

Convert React class component to React Hook

Im trying to convert the following code to react hook component, but I don't understand how to convert the onOrderChange and the consts in the render parts to react hooks, how do I go about this? My goal is to have a drag and drop-able react checkbox tree component but I'm unable to convert the drag and drop part to react hooks, the other parts are in react hooks.
import React from 'react';
import CheckboxTree from 'react-checkbox-tree-reorderable';
const nodesData = './data.json'
class BasicExample extends React.Component {
state = {
nodes: nodesData,
checked:[],
expanded: [],
};
constructor(props) {
super(props);
this.onCheck = this.onCheck.bind(this);
this.onExpand = this.onExpand.bind(this);
}
onCheck(checked) {
this.setState({ checked });
}
onExpand(expanded) {
this.setState({ expanded });
}
onOrderChange = (orderedNodes) => {
this.setState({
nodes: orderedNodes,
});
}
render() {
const { onOrderChange, state } = this;
const { checked, expanded, nodes } = state;
return (
<CheckboxTree
checked={checked}
expanded={expanded}
iconsClass="fa5"
nodes={nodes}
onCheck={this.onCheck}
onExpand={this.onExpand}
orderable
onOrderChange={onOrderChange}
/>
);
}
}
export default BasicExample;
This is my data.json file
[
{
"value": "polygon",
"label": "Polygon",
"type": "parent",
"children": [
{
"value": "ward",
"label": "Ward",
"type": "fill",
"source": {
"type": "geojson",
"data": "/Ward.json"
},
"id": "ward",
"paint": {
"fill-color": "red",
"fill-opacity": 0.2
},
"layout": {
"visibility": "none"
},
"filter": [
"all"
]
},
{
"value": "zone",
"label": "Zone",
"type": "fill",
"source": {
"type": "geojson",
"data": "/Zone.json"
},
"id": "zone",
"paint": {
"fill-color": "blue",
"fill-opacity": 0.2
},
"layout": {
"visibility": "none"
},
"filter": [
"all"
]
}
]
},
{
"value": "line",
"label": "Line",
"type": "parent",
"children": [
{
"value": "path",
"label": "Path",
"type": "parent",
"children": [
{
"value": "roads",
"label": "Roads",
"type": "line",
"source": {
"type": "geojson",
"data": "/Roads.json"
},
"id": "roads",
"paint": {
"line-color": "orange"
},
"layout": {
"visibility": "none"
},
"filter": [
"all"
]
},
{
"value": "footpaths",
"label": "Footpaths",
"type": "line",
"source": {
"type": "geojson",
"data": "/Footpaths.json"
},
"id": "footpaths",
"paint": {
"line-color": "pink"
},
"layout": {
"visibility": "none"
},
"filter": [
"all"
]
}
]
},
{
"value": "drainage",
"label": "Drainage",
"type": "parent",
"children": [
{
"value": "waste",
"label": "Waste",
"type": "line",
"source": {
"type": "geojson",
"data": "/Waste.json"
},
"id": "waste",
"paint": {
"line-color": "brown"
},
"layout": {
"visibility": "none"
},
"filter": [
"all"
]
},
{
"value": "storm",
"label": "Storm",
"type": "line",
"source": {
"type": "geojson",
"data": "/Storm.json"
},
"id": "storm",
"paint": {
"line-color": "green"
},
"layout": {
"visibility": "none"
},
"filter": [
"all"
]
}
]
}
]
}
]
Refer this and go through the code below..
https://olinations.medium.com/10-steps-to-convert-a-react-class-component-to-a-functional-component-with-hooks-ab198e0fa139
import React, { useState } from "react";
import CheckboxTree from "react-checkbox-tree-reorderable";
const nodesData = "./data.json";
const BasicExample = () => {
const [checked, setChecked] = useState("");
const [expanded, setExpand] = useState("");
const [nodes, setOrderNodes] = useState(nodesData);
const onCheck = (checked) => setChecked(checked);
const onExpand = (expanded) => setExpand(expanded);
const onOrderChange = (orderedNodes) => setOrderNodes(orderedNodes);
return (
<CheckboxTree
checked={checked}
expanded={expanded}
iconsClass="fa5"
nodes={nodes}
onCheck={onCheck}
onExpand={onExpand}
orderable
onOrderChange={onOrderChange}
/>
);
};
export default BasicExample;

How to prevent fields in react-json-schema-form from appearing row by row

I am creating forms using React-json-schema-form. I don't understand how am I suppose to change the layout of the forms I create. They appear in rows by default and adding classes to each field in the uiSchema does not reflect the desired change. I tried adding col-3 etc and they neither change size nor stop appearing in rows.
Its so complex to figure out. My understand would be to change the default behaviour of the fields. But, I'm sure it should be able to be designed out of the box right?
This is what I want to do but its outdated and I still don't know how to use it. https://github.com/audibene-labs/react-jsonschema-form-layout.
How do I change the layout?
import React, { Component, Fragment } from "react";
import axios, { existing_api, new_api, public_path } from "../../../Api/api";
import 'bootstrap/dist/css/bootstrap.css';
//import Form from "#rjsf/core";
import Form from "#rjsf/bootstrap-4";
class POSView extends Component {
constructor(props) {
super(props);
this.state = {
hotelId: 1,
isActive: 1,
formData: { 'recordIn': 10096 },
schema: props.schema || {
"title": "POS",
"description": "Add POS Invoice - Rooms",
"type": "object",
"properties": {
"customer": { "title": "Customer", "type": 'string', "default": '' },
"room": { "title": "Room", "type": 'integer', "default": '' },
"address": { "title": "Address", "type": 'string' },
"company": { "title": "Company", "type": 'string' },
"dueAmount": { "title": "Due Amount", "type": 'string' },
"roomRate": { "title": "Room Rate", "type": 'string' },
"recordIn": { "title": "Record In", "type": 'number', enum: [10096, 10097], enumNames: ["Guest Ledger Control A/c", "Accounts Receivable"] },
"department": { "title": "Department", "type": 'number', enum: [1, 2], enumNames: ["Head Office", "Accounts"] },
"id": { "title": "ID", "type": 'string' },
"invoiceNumber": { "title": "Invoice Number", "type": 'string' },
"invoiceDate": { "title": "Invoice Date", "type": 'string', "format": "date-time" },
"btcCompany": { "title": "BTC Company", "type": 'number', enum: [1, 2], enumNames: ["Limited Standard", "Standard Limited"] },
"itemsAndServices":
{
"title": "Item And Service",
"description": "Add items and Services",
"type": "array",
"items": {
"type": "object",
//"required": [''],
"properties":
{
"Number": { "type": "number" },
"Item Name": {
"title": "Item Name",
"type": "string"
},
"Item Notes": {
"title": "Item Notes",
"type": "string"
},
"Qty": {
"title": "Qty",
"type": "number"
},
"Unit": {
"title": "Unit",
"type": "string"
},
"Price": {
"title": "Price",
"type": "number"
},
"%": {
"title": "%",
"type": "number"
},
"Extended": {
"title": "Extended",
"type": "number"
}
}
}
},
"payment":
{
"title": "Payment",
"description": "",
"type": "array",
"items": {
"type": "object",
//"required": [''],
"properties":
{
"date": { "title": "Date", "type": "string", format: "date-time" },
"amount": { "title": "Amount", "type": "number" },
"cheque": { "title": "Cheque #", "type": "integer" },
"memo": { "title": "Memo", "type": "string" },
"recordIn": { "title": "Record In", "type": 'number', enum: [10096, 10097], enumNames: ["Guest Ledger Control A/c", "Accounts Receivable"] },
// dynamically populate
}
}
}
}
},
uiSchema: props.uiSchema || {
// customer:{'className':""},
// room:{'className':"", },
// address: {'className':"", "ui:disabled": true, },
// company: {'className':"", "ui:disabled": true, },
// dueAmount: {'className':"", "ui:disabled": true, },
// roomRate: {'className':"", "ui:disabled": true, },
// recordIn:{'className':"", },
// department:{'className':"", },
// id:{'className':"", },
// invoiceNumber: {'className':"", "ui:disabled": true, },
// invoiceDate:{'className':"", },
// btcCompany:{'className':"", },
// itemsAndServices:{'className':""},
//items: { className: "container col-offset-6 col-md-3" }
// 'ui:field': 'layout', HOW I expected the default library to work
// 'ui:layout': [
// {
// customer: { md: 6 },
// room: { md: 6 }
// }, {
// address: { md: 12 }
// }, {
// company: { md: 6 },
// dueAmount: { md: 6 }
// }
// ]
// },
// fields:
// {
// layout: LayoutField
}
};
this.onChange = this.onChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
};
onChange({ formData }) {
formData.address = "";
console.log(formData);
this.state.schema.description = "this is beta plus plus";
this.setState({
formData: formData,
});
}
handleSubmit({ formData }) {
// Submit to an api
console.log(formData);
}
render() {
return (
<div className="container">
<div className="col-4">
{/* <div class="row">
<h1 class="col">First Form</h1>
</div><br /> */}
<div>
<Form
schema={this.state.schema}
formData={this.state.formData}
uiSchema={this.state.uiSchema}
//fields={this.state.fields}
onChange={this.onChange}
onSubmit={this.handleSubmit} />
</div>
</div>
</div>
);
}
}
export default POSView;

react axios and react-hook form problem put in json

I am a student who is practicing react js, for this I am developing a calendar in which you can put notes, as you will see there are some notes that I have put by hand. I have installed axios to work the json and the get of the data does it well, but when I try to set a new data it gives me this error.
the browser console shows me this error
PATCH http://localhost:5000/January/3/alarms/ 404 (Not Found) Uncaught
(in promise) Error: Request failed with status code 404 at
createError (createError.js:16) at settle (settle.js:17) at
XMLHttpRequest.handleLoad (xhr.js:62)
this is my JSOn
{
"January": [
{
"id": 1,
"alarms": [
{
"name": "Medico",
"initHour": "12:00",
"endHour": "12:35"
},
{
"name": "fisio",
"initHour": "16:00",
"endHour": "17:00"
},
{
"name": "desayuno con Rick",
"initHour": "8:00",
"endHour": "9:00"
}
]
},
{
"id": 2,
"alarms": [
{
"name": "Desayuno",
"initHour": "9:00",
"endHour": "9:35"
},
{
"name": "banco",
"initHour": "11:00",
"endHour": "12:00"
}
]
},
{
"id": 3,
"alarms": []
},{
"id": 4,
"alarms": []
},
{
"id": 5,
"alarms": []
},
{
"id": 6,
"alarms": []
},
{
"id": 7,
"alarms": []
},
{
"id": 8,
"alarms": []
},
{
"id": 9,
"alarms": [
{
"name": "fisio",
"initHour": "16:00",
"endHour": "17:00"
}
]
},
{
"id": 10,
"alarms": []
},
{
"id": 11,
"alarms": []
},
{
"id": 12,
"alarms": []
},
{
"id": 13,
"alarms": []
},
{
"id": 14,
"alarms": []
},
{
"id": 15,
"alarms": []
},
{
"id": 16,
"alarms": [
{
"name": "fisio",
"initHour": "16:00",
"endHour": "17:00"
}
]
},
{
"id": 17,
"alarms": []
},
{
"id": 18,
"alarms": []
},
{
"id": 19,
"alarms": []
},
{
"id": 20,
"alarms": []
},
{
"id": 21,
"alarms": []
},
{
"id": 22,
"alarms": []
},
{
"id": 23,
"alarms": [
{
"name": "fisio",
"initHour": "16:00",
"endHour": "17:00"
}
]
},
{
"id": 24,
"alarms": []
},
{
"id": 25,
"alarms": []
},
{
"id": 26,
"alarms": []
},
{
"id": 27,
"alarms": []
},
{
"id": 28,
"alarms": []
},
{
"id": 29,
"alarms": []
},
{
"id": 30,
"alarms": [
{
"name": "fisio",
"initHour": "16:00",
"endHour": "17:00"
}
]
},
{
"id": 31,
"alarms": []
}
]
}
and this is my code
import React, {useEffect, useState} from "react";
import './Calendar.scss';
import axios from "axios";
import Day from "./Day/Day";
import Modal from 'react-modal';
import { useForm } from 'react-hook-form';
const customStyles = {
content : {
top : '50%',
left : '50%',
right : 'auto',
bottom : 'auto',
marginRight : '-50%',
transform : 'translate(-50%, -50%)'
}
};
export default function Calendar() {
let subtitle;
const { register, handleSubmit} = useForm();
const [days, setDays] = useState([]);
const [modalIsOpen,setIsOpen] = useState(false);
const [id, setId] = useState([]);
Modal.setAppElement('#root')
useEffect(() => {
axios.get('http://localhost:5000/January').then(res => {
setDays(res.data);
});
}, [])
const onSubmit = form => {
console.log('http://localhost:5000/January/' + id + '/alarms', form);
axios.patch('http://localhost:5000/January/' + id + '/alarms/', form).then(res => {
console.log(res);
});
}
function openModal(id) {
setIsOpen(true);
setId(id);
}
function afterOpenModal() {
// references are now sync'd and can be accessed.
subtitle.style.color = 'rgb(72, 181, 163)';
}
function closeModal(){
setIsOpen(false);
}
return (
<div className="b-calendar">
<h3 className="b-calendar__title">January</h3>
<div className="b-calendar__headers">
<div>Monday</div>
<div>Tuesday</div>
<div>Wednesday</div>
<div>Thursday</div>
<div>Friday</div>
<div>Saturday</div>
<div>Sunday</div>
</div>
<div className="b-calendar__content">
<div className="b-december"><h1>28</h1></div>
<div className="b-december"><h1>29</h1></div>
<div className="b-december"><h1>30</h1></div>
<div className="b-december"><h1>31</h1></div>
{days.map((item, index) =>
<div key={index+1} id={index+1} onClick={() => openModal(item.id)}>
<Day items={item}/>
</div>
)}
</div>
<Modal
isOpen={modalIsOpen}
onAfterOpen={afterOpenModal}
onRequestClose={closeModal}
style={customStyles}
contentLabel="Example Modal"
>
<h2 ref={_subtitle => (subtitle = _subtitle)}>Añadir Cita</h2>
<form className="b-loginForm" onSubmit={handleSubmit(onSubmit)}>
<label htmlFor="initHour">
<span className="b-text-label">Init hour</span>
<input id="initHour" className="b-input" type="time" name="initHour" ref={register({ required: true})} />
</label>
<label htmlFor="endHour">
<span className="b-text-label">End hour</span>
<input id="endHour" className="b-input" type="time" name="endHour" ref={register()} />
</label>
<label htmlFor="name">
<span className="b-text-label">Alarms name</span>
<input id="name" className="b-input" type="text" name="name" ref={register({ required: true})} />
</label>
<input className="b-btn" type="submit" value="Guardar" />
<button onClick={closeModal}>Salir</button>
</form>
</Modal>
</div>
)
}```
[1]: https://i.stack.imgur.com/PDVPD.png

Displaying list dynamically in react when user click on input filed

I am trying to display list dynamically when user click on input box. for that I took onChange event handle on input box and setting state to new data when user click on input box. but it is not giving me desired result. can anyone help me to solve the issue ? When user click on input box then only list should be displayed but in my case it's displaying already.
SearchBox.js
import React, { Component } from "react";
import SourceData from "../assets/continents.json";
class SearchBox extends Component {
state = {
value: ""
};
handleChange = e => {
this.setState({
sourceData: SourceData
});
};
render() {
const searhBox = (
<input type="text" value={this.state.value} onClick={this.handleChange} />
);
const selectBox2 = SourceData.map(option => <li>{option.continent}</li>);
return (
<React.Fragment>
<h2>Step 1</h2>
<h3>Select a continent.</h3>
{searhBox}
<ul>{selectBox2}</ul>
</React.Fragment>
);
}
}
export default SearchBox
continents.json
[
{
"continent": "Africa",
"countries": [
{
"name": "Nigeria",
"flag": "ð³ð¬"
},
{
"name": "Ethiopia",
"flag": "ðªð¹"
},
{
"name": "Egypt",
"flag": "ðªð¬"
},
{
"name": "DR Congo",
"flag": "ð¨ð©"
},
{
"name": "South Africa",
"flag": "ð¿ð¦"
}
]
},
{
"continent": "America",
"countries": [
{
"name": "USA",
"flag": "ðºð¸"
},
{
"name": "Brazil",
"flag": "ð§ð·"
},
{
"name": "Mexico",
"flag": "ð²ð½"
},
{
"name": "Colombia",
"flag": "ð¨ð´"
},
{
"name": "Argentina",
"flag": "ð¦ð·"
}
]
},
{
"continent": "Asia",
"countries": [
{
"name": "China",
"flag": "ð¨ð³"
},
{
"name": "India",
"flag": "ð®ð³"
},
{
"name": "Indonesia",
"flag": "ð®ð©"
},
{
"name": "Pakistan",
"flag": "ðµð°"
},
{
"name": "Bangladesh",
"flag": "ð§ð©"
}
]
}
]
output ::
In SearchBox.render, build up the list of countries from this.state.sourceData
const selectBox2 = this.state.sourceData.map(option => <li>{option.continent}</li>);
return (
<React.Fragment>
<h2>Step 1</h2>
<h3>Select a continent.</h3>
{searhBox}
{selectBox2 && <ul>{selectBox2}</ul>}
</React.Fragment>
);
Also, remember to set an initial value for sourceData in SearchBox.state.
state = {
value: '',
sourceData: []
};

Resources