Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement dedicated share model component for sharing links 🚀🔥 #1588

Merged
merged 1 commit into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 55 additions & 23 deletions src/components/Card/GridView.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { useContext } from 'react';
import { useContext, useState } from 'react';
import { ToolContext } from '../../App';
import ShareModel from './ShareModel';
import '../../styles/GridView.css';

const GridView = ({ currentProducts }) => {
const [isCopied, setIsCopied] = useState(false); // State to track whether link is copied
const { handelBookmarkAdd, bookmarks, deleteres, darkMode } = useContext(ToolContext);
const [cardModalVisibility, setCardModalVisibility] = useState(false);
const [customShareLink, setCustomShareLink] = useState('');


const handleShareClick = async (product) => {
try {
// Check if the Web Share API is available in the browser
if (navigator.share) {
let customShareLink = `${window.location.href.split('?')[0]}?q=${encodeURIComponent(
product.productName
Expand All @@ -19,36 +23,54 @@ const GridView = ({ currentProducts }) => {
url: customShareLink,
});
} else {
// Fallback for browsers that do not support the Web Share API
const customShareLink = `${window.location.origin}/?q=${encodeURIComponent(
product.productName
)}`;

// Copy the link to the clipboard
await navigator.clipboard.writeText(customShareLink);
alert('Link copied!');
console.log("Web Share API is not supported in this browser.")
setCardModalVisibility(true);
const link = `${window.location.origin}/?q=${encodeURIComponent(product.productName)}`;
setCustomShareLink(link);
// await navigator.clipboard.writeText(link);
console.log('Link copied!');
console.log("Web Share API is not supported in this browser.");
}
} catch (error) {
console.error('Error sharing:', error);
}
};

const handleCopyLink = () => {
try {
navigator.clipboard.writeText(customShareLink);
console.log('Link copied!');

setIsCopied(true); // Set the state to indicate link is copied
setTimeout(() => {
setIsCopied(false); // Reset the state after a delay
}, 3000); // Reset after 3 seconds
} catch (error) {
console.error('Error copying link:', error);
}
};

const handleShareModalClose = () => {
setCardModalVisibility(false);
};

return (
<main className={`grid ${darkMode ? 'dark-mode' : ''}`}>
<main
className={`grid ${darkMode ? 'dark-mode' : ''}`}
style={{ userSelect: cardModalVisibility ? 'none' : 'auto' }}
>
{currentProducts.map((product, index) => (
<article key={index}>
<div className="text_top">
{product.image ? (
<div className='card-image'>
<img
className={`${darkMode ? 'dark-mode' : ''}`}
src={product.image}
alt="product-img"
onError={(e) => {
e.target.src = 'https://i.ibb.co/9H0s34n/default-img.jpg';
}}
/>
className={`${darkMode ? 'dark-mode' : ''}`}
src={product.image}
alt="product-img"
onError={(e) => {
e.target.src = 'https://i.ibb.co/9H0s34n/default-img.jpg';
}}
/>
</div>
) : (
<img
Expand All @@ -57,9 +79,9 @@ const GridView = ({ currentProducts }) => {
alt="Default"
/>
)}
<h2 className={`card-title ${darkMode ? 'dark-mode' : ''}`}>{product.productName.charAt(0).toUpperCase() + product.productName.slice(1,)}</h2>

{/* Share icon and implement the click event */}
<h2 className={`card-title ${darkMode ? 'dark-mode' : ''}`}>
{product.productName.charAt(0).toUpperCase() + product.productName.slice(1)}
</h2>
<button
className={`share-icon`}
onClick={() => handleShareClick(product)}
Expand All @@ -70,7 +92,9 @@ const GridView = ({ currentProducts }) => {
></i>
</button>
</div>
<p className={`card-description ${darkMode ? 'dark-mode' : ''}`}>{product.description}</p>
<p className={`card-description ${darkMode ? 'dark-mode' : ''}`}>
{product.description}
</p>
<div className="btn-cont">
<a target="_blank" href={product.link}>
<button className={`visit ${darkMode ? 'dark-mode' : ''}`}>
Expand Down Expand Up @@ -102,6 +126,14 @@ const GridView = ({ currentProducts }) => {
</div>
</article>
))}
<ShareModel
isVisible={cardModalVisibility}
link={customShareLink}
darkMode={darkMode}
onClose={handleShareModalClose}
onCopy={handleCopyLink}
isCopied={isCopied} // Pass the isCopied state
/>
</main>
);
}
Expand Down
50 changes: 38 additions & 12 deletions src/components/Card/ListView.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
import { useContext } from 'react';
import { useContext, useState } from 'react';
import { ToolContext } from '../../App';
import ShareModel from './ShareModel';
import '../../styles/ListView.css';
import { Box, Accordion, AccordionButton, AccordionItem, AccordionPanel, AccordionIcon } from '@chakra-ui/react';
import { BsChevronDown } from 'react-icons/bs';

const ListView = ({ currentProducts }) => {
const { handelBookmarkAdd, bookmarks, deleteres, darkMode } = useContext(ToolContext);
const [cardModelVisibility, setCardModelVisibility] = useState(false);
const [customShareLink, setCustomShareLink] = useState('');
const [isCopied, setIsCopied] = useState(false); // State to track copied status

const handleCopyLink = async () => {
try {
await navigator.clipboard.writeText(customShareLink);
setIsCopied(true); // Set copied status to true
setTimeout(() => setIsCopied(false), 1500); // Reset copied status after 1.5 seconds
console.log('Link copied!');
} catch (error) {
console.error('Error copying link:', error);
}
};

const handleShareModelClose = () => {
setCardModelVisibility(false);
};

const handleShareClick = async (product) => {
try {
// Check if the Web Share API is available in the browser
if (navigator.share) {
let customShareLink = `${window.location.href.split('?')[0]}?q=${encodeURIComponent(
product.productName
Expand All @@ -20,22 +39,20 @@ const ListView = ({ currentProducts }) => {
url: customShareLink,
});
} else {
// Fallback for browsers that do not support the Web Share API
const customShareLink = `${window.location.origin}/?q=${encodeURIComponent(
product.productName
)}`;

// Copy the link to the clipboard
await navigator.clipboard.writeText(customShareLink);
alert('Link copied!');
console.log("Web Share API is not supported in this browser.")
setCardModelVisibility(true);
const link = `${window.location.origin}/?q=${encodeURIComponent(product.productName)}`;
setCustomShareLink(link);
}
} catch (error) {
console.error('Error sharing:', error);
}
};
return (
<Accordion allowToggle className={`list ${darkMode ? 'dark-mode' : ''}`}>
<Accordion
allowToggle
className={`list ${darkMode ? 'dark-mode' : ''}`}
style={{ userSelect: cardModelVisibility ? 'none' : 'auto' }}
>
{currentProducts.map((product, index) => (
<AccordionItem
borderRadius="8px"
Expand Down Expand Up @@ -147,6 +164,15 @@ const ListView = ({ currentProducts }) => {
</AccordionPanel>
</AccordionItem>
))}
{/* Use the ShareModel component */}
<ShareModel
isVisible={cardModelVisibility}
link={customShareLink}
darkMode={darkMode}
onClose={handleShareModelClose}
onCopy={handleCopyLink}
isCopied={isCopied}
/>
</Accordion>
);
};
Expand Down
106 changes: 106 additions & 0 deletions src/components/Card/ShareModel.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import React from 'react';
import { FaRegCopy, FaTimes } from 'react-icons/fa';
import '../../styles/shareModel.css';

const ShareModel = ({ darkMode, isVisible, link, onClose, onCopy, isCopied }) => {
return isVisible ? (
<div
className="share-model"
style={{
position: 'fixed',
inset: 0,
background: darkMode ? 'rgba(0, 0, 0, 0.4)' : 'rgba(0, 0, 0, 0.7)',
zIndex: 999,
display: 'grid',
placeItems: 'center',
}}
>
<div
className="model-content"
style={{
maxWidth: '24rem',
background: darkMode ? 'rgb(67, 67, 67)' : 'rgb(241, 241, 241)',
color: darkMode ? '#fff' : 'rgb(34, 34, 34)',
padding: '2rem',
position: 'relative',
borderRadius: '.5rem',
display: 'grid',
gap: '1rem',
placeItems: 'center',
}}
>
<h2 style={{ fontSize: '1.25rem', fontWeight: 500 }}>
Share This Resource
<span
style={{
textShadow: darkMode ? '0px 2px 6px #fff6':'0px 2px 6px #0006',
marginLeft: '.5rem',
fontSize: '1.5rem'
}}
>
💡
</span>
</h2>
<div
className="copy-wrapper"
style={{
display: 'flex',
alignItems: 'center',
gap: '.5rem',
outline: '1px solid grey',
borderRadius: '.25rem',
padding: '.5rem',
position: 'relative',
}}
>
<p
style={{
whiteSpace: 'nowrap',
maxWidth: '17rem',
overflowX: 'scroll',
scrollbarWidth: 'thin',
scrollbarGutter: 'stable',
scrollbarColor: darkMode ? '#fff3 #0003' : '#0003 #fff3',
fontSize: '1rem'
}}
>
{link}
</p>
<button onClick={onCopy} title={'Copy'}>
<FaRegCopy />
</button>
{isCopied && (
<div
className="tooltip"
style={{
position: 'absolute',
fontSize: '.75rem',
top: '-1.5rem',
right: '-0.5rem',
background: '#333',
color: 'white',
padding: '.5rem .75rem',
borderRadius: '.75rem',
}}
>
Copied
</div>
)}
</div>
<button
onClick={onClose}
style={{
position: 'absolute',
top: '.6rem',
right: '.6rem',
}}
aria-label='close'
>
<FaTimes />
</button>
</div>
</div>
) : null;
};

export default ShareModel;
1 change: 0 additions & 1 deletion src/styles/GridView.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
--primary-black: #373530;
}


.grid .card-title{
color: var(--primary-black);
}
Expand Down
9 changes: 9 additions & 0 deletions src/styles/shareModel.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.share-model {
position: fixed;
inset: 0;
background: #fff;
z-index: 99;
color: black;
display: grid;
place-items: center;
}