feat: Ability to keywords for both mobile and desktop at once.

closes #60, #66, #199
This commit is contained in:
towfiqi 2024-11-08 12:28:13 +06:00
parent f48288473e
commit 3786438662

View File

@ -1,4 +1,4 @@
import React, { useMemo, useRef, useState } from 'react'; import React, { useCallback, useMemo, useRef, useState } from 'react';
import Icon from '../common/Icon'; import Icon from '../common/Icon';
import Modal from '../common/Modal'; import Modal from '../common/Modal';
import SelectField from '../common/SelectField'; import SelectField from '../common/SelectField';
@ -23,10 +23,11 @@ type KeywordsInput = {
} }
const AddKeywords = ({ closeModal, domain, keywords, scraperName = '', allowsCity = false }: AddKeywordsProps) => { const AddKeywords = ({ closeModal, domain, keywords, scraperName = '', allowsCity = false }: AddKeywordsProps) => {
const [error, setError] = useState<string>('');
const [showTagSuggestions, setShowTagSuggestions] = useState(false);
const inputRef = useRef(null); const inputRef = useRef(null);
const defCountry = localStorage.getItem('default_country') || 'US'; const defCountry = localStorage.getItem('default_country') || 'US';
const [error, setError] = useState<string>('');
const [showTagSuggestions, setShowTagSuggestions] = useState(false);
const [newKeywordsData, setNewKeywordsData] = useState<KeywordsInput>({ keywords: '', device: 'desktop', country: defCountry, domain, tags: '' }); const [newKeywordsData, setNewKeywordsData] = useState<KeywordsInput>({ keywords: '', device: 'desktop', country: defCountry, domain, tags: '' });
const { mutate: addMutate, isLoading: isAdding } = useAddKeywords(() => closeModal(false)); const { mutate: addMutate, isLoading: isAdding } = useAddKeywords(() => closeModal(false));
@ -35,23 +36,45 @@ const AddKeywords = ({ closeModal, domain, keywords, scraperName = '', allowsCit
return [...new Set(allTags)]; return [...new Set(allTags)];
}, [keywords]); }, [keywords]);
const setDeviceType = useCallback((input:string) => {
let updatedDevice = '';
if (newKeywordsData.device.includes(input)) {
updatedDevice = newKeywordsData.device.replace(',', '').replace(input, '');
} else {
updatedDevice = newKeywordsData.device ? `${newKeywordsData.device},${input}` : input;
}
setNewKeywordsData({ ...newKeywordsData, device: updatedDevice });
}, [newKeywordsData]);
const addKeywords = () => { const addKeywords = () => {
if (newKeywordsData.keywords) { const nkwrds = newKeywordsData;
const keywordsArray = [...new Set(newKeywordsData.keywords.split('\n').map((item) => item.trim()).filter((item) => !!item))]; if (nkwrds.keywords) {
const devices = nkwrds.device.split(',');
const multiDevice = nkwrds.device.includes(',') && devices.length > 1;
const keywordsArray = [...new Set(nkwrds.keywords.split('\n').map((item) => item.trim()).filter((item) => !!item))];
const currentKeywords = keywords.map((k) => `${k.keyword}-${k.device}-${k.country}${k.city ? `-${k.city}` : ''}`); const currentKeywords = keywords.map((k) => `${k.keyword}-${k.device}-${k.country}${k.city ? `-${k.city}` : ''}`);
const keywordExist = keywordsArray.filter((k) => currentKeywords.includes(
`${k}-${newKeywordsData.device}-${newKeywordsData.country}${newKeywordsData.city ? `-${newKeywordsData.city}` : ''}`, const keywordExist = keywordsArray.filter((k) =>
)); devices.some((device) => currentKeywords.includes(`${k}-${device}-${nkwrds.country}${nkwrds.city ? `-${nkwrds.city}` : ''}`)),
if ((keywordsArray.length === 1 || currentKeywords.length === keywordExist.length) && keywordExist.length > 0) { );
if (!multiDevice && (keywordsArray.length === 1 || currentKeywords.length === keywordExist.length) && keywordExist.length > 0) {
setError(`Keywords ${keywordExist.join(',')} already Exist`); setError(`Keywords ${keywordExist.join(',')} already Exist`);
setTimeout(() => { setError(''); }, 3000); setTimeout(() => { setError(''); }, 3000);
} else { } else {
const filteredKeywords = keywordsArray.filter((k) => !currentKeywords.includes( const newKeywords = keywordsArray.flatMap((k) =>
`${k}-${newKeywordsData.device}-${newKeywordsData.country}${newKeywordsData.city ? `-${newKeywordsData.city}` : ''}`, devices.filter((device) =>
)); !currentKeywords.includes(`${k}-${device}-${nkwrds.country}${nkwrds.city ? `-${nkwrds.city}` : ''}`),
const { device, country, domain: kDomain, tags, city } = newKeywordsData; ).map((device) => ({
const newKeywordsArray = filteredKeywords.map((nItem) => ({ keyword: nItem, device, country, domain: kDomain, tags, city })); keyword: k,
addMutate(newKeywordsArray); device,
country: nkwrds.country,
domain: nkwrds.domain,
tags: nkwrds.tags,
city: nkwrds.city,
})),
);
addMutate(newKeywords);
} }
} else { } else {
setError('Please Insert a Keyword'); setError('Please Insert a Keyword');
@ -59,7 +82,7 @@ const AddKeywords = ({ closeModal, domain, keywords, scraperName = '', allowsCit
} }
}; };
const deviceTabStyle = 'cursor-pointer px-3 py-2 rounded mr-2'; const deviceTabStyle = 'cursor-pointer px-2 py-2 rounded';
return ( return (
<Modal closeModal={() => { closeModal(false); }} title={'Add New Keywords'} width="[420px]"> <Modal closeModal={() => { closeModal(false); }} title={'Add New Keywords'} width="[420px]">
@ -92,13 +115,17 @@ const AddKeywords = ({ closeModal, domain, keywords, scraperName = '', allowsCit
</div> </div>
<ul className='flex text-xs font-semibold text-gray-500'> <ul className='flex text-xs font-semibold text-gray-500'>
<li <li
className={`${deviceTabStyle} ${newKeywordsData.device === 'desktop' ? ' bg-indigo-50 text-gray-700' : ''}`} className={`${deviceTabStyle} mr-2 ${newKeywordsData.device.includes('desktop') ? ' bg-indigo-50 text-indigo-700' : ''}`}
onClick={() => setNewKeywordsData({ ...newKeywordsData, device: 'desktop' })} onClick={() => setDeviceType('desktop')}>
><Icon type='desktop' classes={'top-[3px]'} size={15} /> <i className='not-italic hidden lg:inline-block'>Desktop</i></li> <Icon type='desktop' classes={'top-[3px]'} size={15} /> <i className='not-italic hidden lg:inline-block'>Desktop</i>
<Icon type='check' classes={'pl-1'} size={12} color={newKeywordsData.device.includes('desktop') ? '#4338ca' : '#bbb'} />
</li>
<li <li
className={`${deviceTabStyle} ${newKeywordsData.device === 'mobile' ? ' bg-indigo-50 text-gray-700' : ''}`} className={`${deviceTabStyle} ${newKeywordsData.device.includes('mobile') ? ' bg-indigo-50 text-indigo-700' : ''}`}
onClick={() => setNewKeywordsData({ ...newKeywordsData, device: 'mobile' })} onClick={() => setDeviceType('mobile')}>
><Icon type='mobile' /> <i className='not-italic hidden lg:inline-block'>Mobile</i></li> <Icon type='mobile' /> <i className='not-italic hidden lg:inline-block'>Mobile</i>
<Icon type='check' classes={'pl-1'} size={12} color={newKeywordsData.device.includes('mobile') ? '#4338ca' : '#bbb'} />
</li>
</ul> </ul>
</div> </div>
<div className='relative'> <div className='relative'>