From a13c786b0bc59dfb802bf46c2d518d143b08fdbd Mon Sep 17 00:00:00 2001 From: sebseb7 Date: Thu, 18 Sep 2025 15:35:13 +0200 Subject: [PATCH] feat(ui): implement share functionality in ProductDetailPage Add a share button with a popper menu to the ProductDetailPage, allowing users to share products via various platforms including WhatsApp, Facebook, and email. Implement snackbar notifications for user feedback on successful actions. Enhance state management to handle share popper and snackbar visibility. --- src/components/ProductDetailPage.js | 246 +++++++++++++++++++++++++++- 1 file changed, 241 insertions(+), 5 deletions(-) diff --git a/src/components/ProductDetailPage.js b/src/components/ProductDetailPage.js index fc44735..a94c835 100644 --- a/src/components/ProductDetailPage.js +++ b/src/components/ProductDetailPage.js @@ -1,5 +1,12 @@ import React, { Component } from "react"; -import { Box, Container, Typography, CardMedia, Stack, Chip, Button, Collapse } from "@mui/material"; +import { Box, Container, Typography, CardMedia, Stack, Chip, Button, Collapse, Popper, ClickAwayListener, MenuList, MenuItem, ListItemIcon, ListItemText, Snackbar, Alert } from "@mui/material"; +import ShareIcon from "@mui/icons-material/Share"; +import WhatsAppIcon from "@mui/icons-material/WhatsApp"; +import FacebookIcon from "@mui/icons-material/Facebook"; +import TelegramIcon from "@mui/icons-material/Telegram"; +import EmailIcon from "@mui/icons-material/Email"; +import LinkIcon from "@mui/icons-material/Link"; +import CodeIcon from "@mui/icons-material/Code"; import { Link } from "react-router-dom"; import parse from "html-react-parser"; import AddToCartButton from "./AddToCartButton.js"; @@ -83,7 +90,14 @@ class ProductDetailPage extends Component { // Collapsible sections state showQuestionForm: false, showRatingForm: false, - showAvailabilityForm: false + showAvailabilityForm: false, + // Share popper state + shareAnchorEl: null, + sharePopperOpen: false, + // Snackbar state + snackbarOpen: false, + snackbarMessage: "", + snackbarSeverity: "success" }; } else if (partialProduct && isUpgrading) { // Partial product data found - enter upgrading state @@ -123,7 +137,14 @@ class ProductDetailPage extends Component { // Collapsible sections state showQuestionForm: false, showRatingForm: false, - showAvailabilityForm: false + showAvailabilityForm: false, + // Share popper state + shareAnchorEl: null, + sharePopperOpen: false, + // Snackbar state + snackbarOpen: false, + snackbarMessage: "", + snackbarSeverity: "success" }; } else { // No cached data found - full loading state @@ -145,7 +166,14 @@ class ProductDetailPage extends Component { // Collapsible sections state showQuestionForm: false, showRatingForm: false, - showAvailabilityForm: false + showAvailabilityForm: false, + // Share popper state + shareAnchorEl: null, + sharePopperOpen: false, + // Snackbar state + snackbarOpen: false, + snackbarMessage: "", + snackbarSeverity: "success" }; } } @@ -634,8 +662,116 @@ class ProductDetailPage extends Component { } }; + // Share functionality + handleShareClick = (event) => { + this.setState({ + shareAnchorEl: event.currentTarget, + sharePopperOpen: true + }); + }; + + handleShareClose = () => { + this.setState({ + shareAnchorEl: null, + sharePopperOpen: false + }); + }; + + showSnackbar = (message, severity = "success") => { + this.setState({ + snackbarOpen: true, + snackbarMessage: message, + snackbarSeverity: severity + }); + }; + + handleSnackbarClose = (event, reason) => { + if (reason === 'clickaway') { + return; + } + this.setState({ snackbarOpen: false }); + }; + + getProductUrl = () => { + return `${window.location.origin}/Artikel/${this.props.seoName}`; + }; + + handleEmbedShare = () => { + const embedCode = ``; + navigator.clipboard.writeText(embedCode).then(() => { + this.showSnackbar("Einbettungscode wurde in die Zwischenablage kopiert!"); + }).catch(() => { + // Fallback for older browsers + try { + const textArea = document.createElement('textarea'); + textArea.value = embedCode; + document.body.appendChild(textArea); + textArea.select(); + document.execCommand('copy'); + document.body.removeChild(textArea); + this.showSnackbar("Einbettungscode wurde in die Zwischenablage kopiert!"); + } catch { + this.showSnackbar("Fehler beim Kopieren des Einbettungscodes", "error"); + } + }); + this.handleShareClose(); + }; + + handleWhatsAppShare = () => { + const url = this.getProductUrl(); + const text = `Schau dir dieses Produkt an: ${cleanProductName(this.state.product.name)}`; + const whatsappUrl = `https://wa.me/?text=${encodeURIComponent(text + ' ' + url)}`; + window.open(whatsappUrl, '_blank'); + this.handleShareClose(); + }; + + handleFacebookShare = () => { + const url = this.getProductUrl(); + const facebookUrl = `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`; + window.open(facebookUrl, '_blank'); + this.handleShareClose(); + }; + + handleTelegramShare = () => { + const url = this.getProductUrl(); + const text = `Schau dir dieses Produkt an: ${cleanProductName(this.state.product.name)}`; + const telegramUrl = `https://t.me/share/url?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}`; + window.open(telegramUrl, '_blank'); + this.handleShareClose(); + }; + + handleEmailShare = () => { + const url = this.getProductUrl(); + const subject = `Produktempfehlung: ${cleanProductName(this.state.product.name)}`; + const body = `Hallo,\n\nich möchte dir dieses Produkt empfehlen:\n\n${cleanProductName(this.state.product.name)}\n${url}\n\nViele Grüße`; + const emailUrl = `mailto:?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`; + window.location.href = emailUrl; + this.handleShareClose(); + }; + + handleLinkCopy = () => { + const url = this.getProductUrl(); + navigator.clipboard.writeText(url).then(() => { + this.showSnackbar("Link wurde in die Zwischenablage kopiert!"); + }).catch(() => { + // Fallback for older browsers + try { + const textArea = document.createElement('textarea'); + textArea.value = url; + document.body.appendChild(textArea); + textArea.select(); + document.execCommand('copy'); + document.body.removeChild(textArea); + this.showSnackbar("Link wurde in die Zwischenablage kopiert!"); + } catch { + this.showSnackbar("Fehler beim Kopieren des Links", "error"); + } + }); + this.handleShareClose(); + }; + render() { - const { product, loading, upgrading, error, attributeImages, isSteckling, attributes, komponentenLoaded, komponentenData, komponentenImages, totalKomponentenPrice, totalSavings } = + const { product, loading, upgrading, error, attributeImages, isSteckling, attributes, komponentenLoaded, komponentenData, komponentenImages, totalKomponentenPrice, totalSavings, shareAnchorEl, sharePopperOpen, snackbarOpen, snackbarMessage, snackbarSeverity } = this.state; // Debug alerts removed @@ -1127,8 +1263,32 @@ class ProductDetailPage extends Component { background: "#fff", borderRadius: 2, boxShadow: "0 2px 8px rgba(0,0,0,0.08)", + position: "relative", }} > + {/* Share button */} + )} + {/* Share Popper */} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {/* Article Question Form */}
@@ -1379,9 +1598,26 @@ class ProductDetailPage extends Component { )} + + {/* Snackbar for user feedback */} + + + {snackbarMessage} + + ); } } export default withI18n()(ProductDetailPage); +