#javascript #reactjs #react-redux #lodash
Вопрос:
У меня есть такая страница, как эта, см. страницу
Он выполняет фильтрацию и все такое. Но, тем не менее, я хочу добавить уровень под названием «Верхний базовый» к каждому языку, если язык:
- Японский
- Немецкий
- Голландский
- Итальянская
- Арабский
- Китайский
- Русский
- Испанский
- Французский
- Корейский
Мой код для этой страницы таков:
import React from 'react';
import NavigationWithCart from '../../components/navbar/Navigation';
import _, { result } from 'lodash';
import {
Box,
Heading,
Text,
Grid,
Button,
Select,
Icon,
Divider,
Badge,
Flex,
Stack
} from '@chakra-ui/react';
import './ChooseClass.css';
import {
ArrowBackIcon,
ArrowForwardIcon
} from '@chakra-ui/icons';
import 'tachyons';
import LANGUAGEIMG from '../../images/choose-language-img/ChooseClassImg';
import {
BiCalendarEdit,
BiUser
} from 'react-icons/bi';
import './ChooseClass.css';
import { store } from '../..';
import { connect } from 'react-redux';
import TYPES from './Objects/TYPES';
import LEVELS from './Objects/LEVELS';
import { filterLanguage, filterType, filterLevel, selectClass, removeClass } from '../../redux/actions';
// document.getElementsByClassName('css-1ro341c')[0]
const mapStateToProps = state => {
return {
selectedLanguage: state.shoppingProcess.selectedLanguage,
selectedLevel: state.shoppingProcess.selectedLevel,
filteredLanguage: state.filterItems.language,
filteredType: state.filterItems.type,
filteredLevel: state.filterItems.level
}
}
const mapDispatchToProps = (dispatch) => {
return {
onFilterLanguage: (e) => dispatch(filterLanguage(e.target.value)),
onFilterType: (e) => dispatch(filterType(e.target.value)),
onFilterLevel: (e) => dispatch(filterLevel(e.target.value)),
onSelectClass: (e) => {
let oldSelected = document.getElementsByClassName('select-class shadow-5');
if (oldSelected.length !== 0) {
oldSelected[0].classList.remove('shadow-5');
dispatch(selectClass(JSON.parse(e.target.dataset.json)));
e.target.classList.add('shadow-5');
} else {
console.log('none');
dispatch(selectClass(JSON.parse(e.target.dataset.json)));
e.target.classList.add('shadow-5');
}
},
onDeleteClass: () => dispatch(removeClass())
}
}
class ChooseClass extends React.Component{
componentDidMount(){
this.props.onDeleteClass();
}
render(){
const FilterLanguageItems = () => {
return (
LANGUAGEIMG.filter(item => item.value !== this.props.selectedLanguage).map(filteredItem => (
<option key={filteredItem.value} value={filteredItem.value}>{capitalizeFirstLetter(filteredItem.value) ' ' countryToFlag(filteredItem.code)}</option>
)))
}
const FilterTypeItems = () => {
return (
TYPES.map(item => (
<option key={item.value} value={item.value}>{item.value}</option>
)))
}
const FilterLevelItems = () => {
return (
LEVELS.map(item => (
<option key={item.value} value={item.value}>{item.value}</option>
)
))
}
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() string.slice(1);
}
function countryToFlag(isoCode) {
return typeof String.fromCodePoint !== 'undefined'
? isoCode
.toUpperCase()
.replace(/./g, (char) => String.fromCodePoint(char.charCodeAt(0) 127397))
: isoCode;
}
const LanguageBox = () => {
let languageIsFiltered = store.getState().filterItems.language;
let selectedLang = languageIsFiltered?languageIsFiltered:store.getState().shoppingProcess.selectedLanguage;
let filteredType = store.getState().filterItems.type;
let filteredLevel = store.getState().filterItems.level;
return (
LEVELS.filter(item => filteredLevel === 'All'?item.value !== 'All':item.value !== 'All' amp;amp; item.value.includes(filteredLevel)).map((filteredLevel) => (
TYPES.filter(item => filteredType === 'All'?item.value !== 'All':item.value !== 'All' amp;amp; item.value.includes(filteredType)).map((filteredType) => (
LANGUAGEIMG.filter(item => item.value.includes(selectedLang)).map((searchedItem) => {
const rows = [];
rows.push(searchedItem, filteredType, filteredLevel);
console.log(rows);
return (
<Stack key={searchedItem.value} mt={5} maxW={'352px'} display="grid" placeItems="center">
<Box cursor="pointer!important" onClick={this.props.onSelectClass} className="select-class" data-json={'{"language": "' capitalizeFirstLetter(searchedItem.value) '" , "type": "' filteredType.value '", "level": "' filteredLevel.value '"}'} display="grid" borderRadius="20px" position="relative" key={searchedItem.value} w="100%" h="auto">
{searchedItem.label}<Badge borderRadius="10px" p={1} pr={2} pl={2} m={3} position="absolute" color="white" backgroundColor={filteredLevel.color}>{filteredLevel.value}</Badge>
</Box>
<Flex pointerEvents="none" mt={'0px!important'} alignItems='center' direction="row" w="100%" justifyContent="space-between">
<Box w="15%" fontSize="46px">
{countryToFlag(searchedItem.code)}
</Box>
<Box w="35%" pl={2}>
<Text textColor="#23262F" w="100%" fontFamily="Plus Jakarta Sans" fontSize="16px" fontWeight={600}>
{capitalizeFirstLetter(searchedItem.value)}
</Text>
<Text textColor="#777E90" fontFamily="Eudoxus Sans" fontWeight={500} fontSize='14px'>
{filteredType.value}
</Text>
</Box>
<Box w="50%">
<Text p={1} display="flex" justifyContent="flex-end" fontFamily="Plus Jakarta Sans" fontSize="18px" textTransform="uppercase" textColor="#009A9D">
Rp 120.000
</Text>
</Box>
</Flex>
<Divider pointerEvents="none" mt={'0!important'}/>
<Flex pointerEvents="none" dir="column" w="100%">
<Box w="100%" fontSize="12px" fontFamily="Plus Jakarta Sans" textColor="#353945">
<Icon mr={2} as={BiCalendarEdit} w="20px" h="auto" color="#353945"/>
25/05/2021
</Box>
<Box textColor="#353945" fontSize="12px" fontFamily="Plus Jakarta Sans" w="100%" display="flex" justifyContent="flex-end">
<Icon mr={2} color="#353945" as={BiUser} w="20px" h="auto"/>
160 slots
</Box>
</Flex>
</Stack>
)})
))
))
)
}
return (
<Box width="100%" display={{base: 'block', sm: 'block', md: 'block', lg: 'grid'}} placeItems="center">
<Box w="97%" display="grid" placeItems="center" m={{base: 0, sm: 0, md: 0, lg: 2}}>
<NavigationWithCart
val="50%"
/>
</Box>
<Box w={{base: '100%', sm: '100%', md: '100%', lg: "98%"}} p={{base: 1, sm: 1, md: 1, lg:10}} h="100%!important" display="grid" placeItems="center">
<Box w={{base: "90%", sm: "90%", md: '90%', lg: "60%"}}>
<Box w="100%">
<Button onClick={() => window.location.replace('/choose-language')} borderRadius={'20px'} colorScheme="teal" variant="outline" w={'180px'} fontSize={'13px'}>
<Icon as={ArrowBackIcon} mr={2} w="18px" h="auto" />
Back to Language
</Button>
</Box>
<Box w="100%" mt={{base: 5, sm: 5, md: 5, lg: 'unset'}} textAlign="center">
<Heading color="teal" fontWeight={600} textColor="#009A9D" fontFamily="Plus Jakarta Sans">
Choose your class
</Heading>
</Box>
<Divider m={1} mt={4}/>
<Flex w="100%" direction={{base: 'column', sm: 'column', md: 'column', lg:"row"}}>
<Box w="100%" mt={{base: 3, sm: 3, md: 3, lg: 0}} m={{base: 0, sm: 0, md: 0, lg: 3}} mb={{base: 3, sm: 3, md: 1, lg: 3}}>
<Text opacity="60%" fontWeight='bold' fontFamily='Plus Jakarta Sans' fontSize="14px">
LANGUAGE
</Text>
<Select onChange={this.props.onFilterLanguage} value={this.props.filteredLanguage?this.props.filteredLanguage:this.props.selectedLanguage} placeholder={capitalizeFirstLetter(this.props.selectedLanguage)} mt={2} borderRadius="12px">
<FilterLanguageItems/>
</Select>
</Box>
<Box w="100%" m={{base: 0, sm: 0, md: 0, lg: 3}} mb={{base: 3, sm: 3, md: 1, lg: 3}}>
<Text opacity="60%" fontWeight='bold' fontFamily='Plus Jakarta Sans' fontSize="14px">
TYPE
</Text>
<Select onChange={this.props.onFilterType} mt={2} borderRadius="12px" value={this.props.filteredType?this.props.filteredType:this.props.filteredType[0]}>
<FilterTypeItems/>
</Select>
</Box>
<Box w="100%" m={{base: 0, sm: 0, md: 0, lg: 3}} mb={{base: 3, sm: 3, md: 1, lg: 3}}>
<Text opacity="60%" fontWeight='bold' fontFamily='Plus Jakarta Sans' fontSize="14px">
LEVEL
</Text>
<Select onChange={this.props.onFilterLevel} mt={2} borderRadius="12px" value={this.props.filteredLevel?this.props.filteredLevel:this.props.filteredLevel[0]}>
<FilterLevelItems/>
</Select>
</Box>
<Box w="100%" m={{base: 0, sm: 0, md: 0, lg: 3}} mb={{base: 3, sm: 3, md: 1, lg: 3}}>
<Text visibility="hidden" opacity="60%" fontWeight='bold' fontFamily='Plus Jakarta Sans' fontSize="14px">
LANGUAGE
</Text>
<Button w="100%" rightIcon={<ArrowForwardIcon />} mt={2} justifyContent="space-between" borderRadius={12} colorScheme="teal" background="#009A9D" textAlign="start" variant="solid">
Next
</Button>
</Box>
</Flex>
<Grid templateColumns={{base: "repeat(1, 1fr)", sm: "repeat(1, 1fr)", md: "repeat(3, 1fr)"}} gap={10}>
<LanguageBox/>
</Grid>
</Box>
</Box>
</Box>
)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(ChooseClass);
LANGUAGEIMG.js:
const LANGUAGEIMG = [
{code: 'EG', value: 'egyptian', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./ANCIENT-EGYPT.png').default} /></div> },
{code: 'SA', value: 'arabic', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./ARABIC.png').default} /></div> },
{code: 'ID', value: 'batak', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./BATAK.png').default} /></div> },
{code: 'CN', value: 'chinese', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./CHINA.png').default} /></div> },
{code: 'NL', value: 'dutch', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./DUTCH.png').default} /></div>},
{code: 'GB', value: 'english', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./ENG-CONVO.png').default} /></div>},
{code: 'ES', value: 'esperanto', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./ESPERANTO.png').default} /></div>},
{code: 'GF', value: 'french', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./FRENCE.png').default} /></div> },
{code: 'DE', value: 'german', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./GERMAN.png').default} /></div> },
{code: 'IL', value: 'hebrew', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./HEBREW.png').default} /></div> },
{code: 'HU', value: 'hungarian', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./HUNGARIAN.png').default} /></div>},
{code: 'IN', value: 'india', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./INDIA.png').default} /></div>},
{code: 'ID', value: 'indonesia', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./INDONESIA.png').default} /></div>},
{code: 'IT', value: 'italian', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./ITALIAN.png').default} /></div> },
{code: 'JP', value: 'japanese', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./JAPANESE.png').default} /></div> },
{code: 'ID', value: 'jawa', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./JAWA.png').default} /></div> },
{code: 'KR', value: 'korean', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./KOREAN.png').default} /></div>},
{code: 'ID', value: 'madura', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./MADURA.png').default} /></div>},
{code: 'NO', value: 'norwegian', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./NORWEGIAN.png').default} /></div>},
{code: 'IR', value: 'persian', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./PERSIAN.png').default} /></div> },
{code: 'PL', value: 'polish', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./POLISH.png').default} /></div> },
{code: 'PT', value: 'portuguese', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./PORTUGUESE.png').default} /></div> },
{code: 'RU', value: 'russian', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./RUSSIAN.png').default} /></div>},
{code: 'SIGN', value: 'sign-language', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./SIGN-LANG.png').default} /></div>},
{code: 'ES', value: 'spanish', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./SPANISH.png').default} /></div>},
{code: 'ID', value: 'sunda', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./SUNDA.png').default} /></div> },
{code: 'NE', value: 'swahili', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./SWAHILI.png').default} /></div> },
{code: 'SE', value: 'swedish', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./SWEDEN.png').default} /></div>},
{code: 'PH', value: 'tagalog', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./TAGALOG.png').default} /></div> },
{code: 'TH', value: 'thai', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./THAI.png').default} /></div> },
{code: 'TR', value: 'turkish', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./TURKISH.png').default} /></div> },
{code: 'PK', value: 'urdu', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./URDU.png').default} /></div> },
{code: 'VN', value: 'vietnamese', label: <div style={{pointerEvents: 'none'}}><img alt=""style={{pointerEvents: 'none', objectFit: 'cover', width: '352px', height: '275px', borderRadius: '18px'}} src={require('./VIETNAM.png').default} /></div> },
]
export default LANGUAGEIMG;
LEVELS.js:
const LEVELS = [
{ value: 'All', color: 'none' },
{ value: 'Beginner', color: '#009A9D' },
// the value i want to add
// { value: 'Upper Basic', color: 'green' },
///
{ value: 'Intermediate', color: '#CB31D8' },
{ value: 'Advanced', color: '#FE7A55' },
]
export default LEVELS;
TYPES.js:
const TYPES = [
{value: 'All'},
{value: 'Basic'},
{value: 'Private'},
{value: 'ETP (TOEFL)'},
{value: 'ETP (IELTS)'}
]
export default TYPES;
Пожалуйста, помогите мне, спасибо
Ответ №1:
Вы можете сделать что-то подобное:
const LEVELS = [
{ value: 'All', color: 'none' },
{ value: 'Beginner', color: '#009A9D' },
{ value: 'Upper Basic', color: 'green', langs: ['Japanese', 'German' /* and so on */] },
{ value: 'Intermediate', color: '#CB31D8' },
{ value: 'Advanced', color: '#FE7A55' },
];
const FilterLevelItems = () => {
return LEVELS
.filter(item => !item.langs || item.langs.includes(this.props.selectedLanguage))
.map(item => <option key={item.value} value={item.value}>{item.value}</option>);
};
Комментарии:
1. Извините, куда мне поместить эту функцию?
2. где вы положили его раньше — внутри
ChooseClass
компонента