merge image and confirmbuy modal and improve on them
This commit is contained in:
parent
ce2574c454
commit
1300cbb0a8
@ -1,12 +1,11 @@
|
|||||||
import { memo, useRef, useState } from "react";
|
import { memo, useRef, useState } from "react";
|
||||||
import AddImageModal from "../modals/AddImageModal";
|
import AddImageModal from "../modals/AddImageModal";
|
||||||
import ConfirmBuyModal from "../modals/ConfirmBuyModal";
|
import ConfirmBuyModal from "../modals/ConfirmBuyModal";
|
||||||
import ImageModal from "../modals/ImageModal";
|
|
||||||
|
|
||||||
function GroceryListItem({ item, onClick, onImageAdded, onLongPress }) {
|
function GroceryListItem({ item, onClick, onImageAdded, onLongPress, allItems = [] }) {
|
||||||
const [showModal, setShowModal] = useState(false);
|
|
||||||
const [showAddImageModal, setShowAddImageModal] = useState(false);
|
const [showAddImageModal, setShowAddImageModal] = useState(false);
|
||||||
const [showConfirmBuyModal, setShowConfirmBuyModal] = useState(false);
|
const [showConfirmBuyModal, setShowConfirmBuyModal] = useState(false);
|
||||||
|
const [currentItem, setCurrentItem] = useState(item);
|
||||||
|
|
||||||
const longPressTimer = useRef(null);
|
const longPressTimer = useRef(null);
|
||||||
const pressStartPos = useRef({ x: 0, y: 0 });
|
const pressStartPos = useRef({ x: 0, y: 0 });
|
||||||
@ -57,13 +56,14 @@ function GroceryListItem({ item, onClick, onImageAdded, onLongPress }) {
|
|||||||
|
|
||||||
const handleItemClick = () => {
|
const handleItemClick = () => {
|
||||||
if (onClick) {
|
if (onClick) {
|
||||||
|
setCurrentItem(item);
|
||||||
setShowConfirmBuyModal(true);
|
setShowConfirmBuyModal(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleConfirmBuy = (quantity) => {
|
const handleConfirmBuy = (quantity) => {
|
||||||
if (onClick) {
|
if (onClick) {
|
||||||
onClick(quantity);
|
onClick(currentItem.id, quantity);
|
||||||
}
|
}
|
||||||
setShowConfirmBuyModal(false);
|
setShowConfirmBuyModal(false);
|
||||||
};
|
};
|
||||||
@ -72,10 +72,16 @@ function GroceryListItem({ item, onClick, onImageAdded, onLongPress }) {
|
|||||||
setShowConfirmBuyModal(false);
|
setShowConfirmBuyModal(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleNavigate = (newItem) => {
|
||||||
|
setCurrentItem(newItem);
|
||||||
|
};
|
||||||
|
|
||||||
const handleImageClick = (e) => {
|
const handleImageClick = (e) => {
|
||||||
e.stopPropagation(); // Prevent triggering the bought action
|
e.stopPropagation(); // Prevent triggering the bought action
|
||||||
if (item.item_image) {
|
if (item.item_image) {
|
||||||
setShowModal(true);
|
// Open buy modal which now shows the image
|
||||||
|
setCurrentItem(item);
|
||||||
|
setShowConfirmBuyModal(true);
|
||||||
} else {
|
} else {
|
||||||
setShowAddImageModal(true);
|
setShowAddImageModal(true);
|
||||||
}
|
}
|
||||||
@ -150,14 +156,6 @@ function GroceryListItem({ item, onClick, onImageAdded, onLongPress }) {
|
|||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
{showModal && (
|
|
||||||
<ImageModal
|
|
||||||
imageUrl={imageUrl}
|
|
||||||
itemName={item.item_name}
|
|
||||||
onClose={() => setShowModal(false)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{showAddImageModal && (
|
{showAddImageModal && (
|
||||||
<AddImageModal
|
<AddImageModal
|
||||||
itemName={item.item_name}
|
itemName={item.item_name}
|
||||||
@ -168,9 +166,11 @@ function GroceryListItem({ item, onClick, onImageAdded, onLongPress }) {
|
|||||||
|
|
||||||
{showConfirmBuyModal && (
|
{showConfirmBuyModal && (
|
||||||
<ConfirmBuyModal
|
<ConfirmBuyModal
|
||||||
item={item}
|
item={currentItem}
|
||||||
onConfirm={handleConfirmBuy}
|
onConfirm={handleConfirmBuy}
|
||||||
onCancel={handleCancelBuy}
|
onCancel={handleCancelBuy}
|
||||||
|
allItems={allItems}
|
||||||
|
onNavigate={handleNavigate}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
@ -187,9 +187,11 @@ export default memo(GroceryListItem, (prevProps, nextProps) => {
|
|||||||
prevProps.item.item_image === nextProps.item.item_image &&
|
prevProps.item.item_image === nextProps.item.item_image &&
|
||||||
prevProps.item.bought === nextProps.item.bought &&
|
prevProps.item.bought === nextProps.item.bought &&
|
||||||
prevProps.item.last_added_on === nextProps.item.last_added_on &&
|
prevProps.item.last_added_on === nextProps.item.last_added_on &&
|
||||||
|
prevProps.item.zone === nextProps.item.zone &&
|
||||||
prevProps.item.added_by_users?.join(',') === nextProps.item.added_by_users?.join(',') &&
|
prevProps.item.added_by_users?.join(',') === nextProps.item.added_by_users?.join(',') &&
|
||||||
prevProps.onClick === nextProps.onClick &&
|
prevProps.onClick === nextProps.onClick &&
|
||||||
prevProps.onImageAdded === nextProps.onImageAdded &&
|
prevProps.onImageAdded === nextProps.onImageAdded &&
|
||||||
prevProps.onLongPress === nextProps.onLongPress
|
prevProps.onLongPress === nextProps.onLongPress &&
|
||||||
|
prevProps.allItems?.length === nextProps.allItems?.length
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,10 +1,21 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import "../../styles/ConfirmBuyModal.css";
|
import "../../styles/ConfirmBuyModal.css";
|
||||||
|
|
||||||
export default function ConfirmBuyModal({ item, onConfirm, onCancel }) {
|
export default function ConfirmBuyModal({
|
||||||
|
item,
|
||||||
|
onConfirm,
|
||||||
|
onCancel,
|
||||||
|
allItems = [],
|
||||||
|
onNavigate
|
||||||
|
}) {
|
||||||
const [quantity, setQuantity] = useState(item.quantity);
|
const [quantity, setQuantity] = useState(item.quantity);
|
||||||
const maxQuantity = item.quantity;
|
const maxQuantity = item.quantity;
|
||||||
|
|
||||||
|
// Find current index and check for prev/next
|
||||||
|
const currentIndex = allItems.findIndex(i => i.id === item.id);
|
||||||
|
const hasPrev = currentIndex > 0;
|
||||||
|
const hasNext = currentIndex < allItems.length - 1;
|
||||||
|
|
||||||
const handleIncrement = () => {
|
const handleIncrement = () => {
|
||||||
if (quantity < maxQuantity) {
|
if (quantity < maxQuantity) {
|
||||||
setQuantity(prev => prev + 1);
|
setQuantity(prev => prev + 1);
|
||||||
@ -21,14 +32,61 @@ export default function ConfirmBuyModal({ item, onConfirm, onCancel }) {
|
|||||||
onConfirm(quantity);
|
onConfirm(quantity);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handlePrev = () => {
|
||||||
|
if (hasPrev && onNavigate) {
|
||||||
|
const prevItem = allItems[currentIndex - 1];
|
||||||
|
onNavigate(prevItem);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNext = () => {
|
||||||
|
if (hasNext && onNavigate) {
|
||||||
|
const nextItem = allItems[currentIndex + 1];
|
||||||
|
onNavigate(nextItem);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const imageUrl = item.item_image && item.image_mime_type
|
||||||
|
? `data:${item.image_mime_type};base64,${item.item_image}`
|
||||||
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="confirm-buy-modal-overlay" onClick={onCancel}>
|
<div className="confirm-buy-modal-overlay" onClick={onCancel}>
|
||||||
<div className="confirm-buy-modal" onClick={(e) => e.stopPropagation()}>
|
<div className="confirm-buy-modal" onClick={(e) => e.stopPropagation()}>
|
||||||
<h2>Mark as Bought</h2>
|
<div className="confirm-buy-header">
|
||||||
<p className="confirm-buy-item-name">"{item.item_name}"</p>
|
{item.zone && <div className="confirm-buy-zone">{item.zone}</div>}
|
||||||
|
<h2 className="confirm-buy-item-name">{item.item_name}</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="confirm-buy-image-section">
|
||||||
|
<button
|
||||||
|
className="confirm-buy-nav-btn confirm-buy-nav-prev"
|
||||||
|
onClick={handlePrev}
|
||||||
|
style={{ visibility: hasPrev ? 'visible' : 'hidden' }}
|
||||||
|
disabled={!hasPrev}
|
||||||
|
>
|
||||||
|
‹
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div className="confirm-buy-image-container">
|
||||||
|
{imageUrl ? (
|
||||||
|
<img src={imageUrl} alt={item.item_name} className="confirm-buy-image" />
|
||||||
|
) : (
|
||||||
|
<div className="confirm-buy-image-placeholder">📦</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
className="confirm-buy-nav-btn confirm-buy-nav-next"
|
||||||
|
onClick={handleNext}
|
||||||
|
style={{ visibility: hasNext ? 'visible' : 'hidden' }}
|
||||||
|
disabled={!hasNext}
|
||||||
|
>
|
||||||
|
›
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="confirm-buy-quantity-section">
|
<div className="confirm-buy-quantity-section">
|
||||||
<p className="confirm-buy-label">Quantity to buy:</p>
|
|
||||||
<div className="confirm-buy-counter">
|
<div className="confirm-buy-counter">
|
||||||
<button
|
<button
|
||||||
onClick={handleDecrement}
|
onClick={handleDecrement}
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import "../../styles/components/EditItemModal.css";
|
import "../../styles/components/EditItemModal.css";
|
||||||
import ClassificationSection from "../forms/ClassificationSection";
|
import ClassificationSection from "../forms/ClassificationSection";
|
||||||
|
import AddImageModal from "./AddImageModal";
|
||||||
|
|
||||||
export default function EditItemModal({ item, onSave, onCancel }) {
|
export default function EditItemModal({ item, onSave, onCancel, onImageUpdate }) {
|
||||||
const [itemName, setItemName] = useState(item.item_name || "");
|
const [itemName, setItemName] = useState(item.item_name || "");
|
||||||
const [quantity, setQuantity] = useState(item.quantity || 1);
|
const [quantity, setQuantity] = useState(item.quantity || 1);
|
||||||
const [itemType, setItemType] = useState("");
|
const [itemType, setItemType] = useState("");
|
||||||
const [itemGroup, setItemGroup] = useState("");
|
const [itemGroup, setItemGroup] = useState("");
|
||||||
const [zone, setZone] = useState("");
|
const [zone, setZone] = useState("");
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [showImageModal, setShowImageModal] = useState(false);
|
||||||
|
|
||||||
// Load existing classification
|
// Load existing classification
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -58,6 +60,18 @@ export default function EditItemModal({ item, onSave, onCancel }) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleImageUpload = async (imageFile) => {
|
||||||
|
if (onImageUpdate) {
|
||||||
|
try {
|
||||||
|
await onImageUpdate(item.id, itemName, quantity, imageFile);
|
||||||
|
setShowImageModal(false);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to upload image:", error);
|
||||||
|
alert("Failed to upload image");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="edit-modal-overlay" onClick={onCancel}>
|
<div className="edit-modal-overlay" onClick={onCancel}>
|
||||||
<div className="edit-modal-content" onClick={(e) => e.stopPropagation()}>
|
<div className="edit-modal-content" onClick={(e) => e.stopPropagation()}>
|
||||||
@ -97,6 +111,19 @@ export default function EditItemModal({ item, onSave, onCancel }) {
|
|||||||
selectClass="edit-modal-select"
|
selectClass="edit-modal-select"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div className="edit-modal-divider" />
|
||||||
|
|
||||||
|
<div className="edit-modal-field">
|
||||||
|
<button
|
||||||
|
className="edit-modal-btn edit-modal-btn-image"
|
||||||
|
onClick={() => setShowImageModal(true)}
|
||||||
|
disabled={loading}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
{item.item_image ? "🖼️ Change Image" : "📷 Set Image"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="edit-modal-actions">
|
<div className="edit-modal-actions">
|
||||||
<button
|
<button
|
||||||
className="edit-modal-btn edit-modal-btn-cancel"
|
className="edit-modal-btn edit-modal-btn-cancel"
|
||||||
@ -114,6 +141,14 @@ export default function EditItemModal({ item, onSave, onCancel }) {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{showImageModal && (
|
||||||
|
<AddImageModal
|
||||||
|
itemName={itemName}
|
||||||
|
onClose={() => setShowImageModal(false)}
|
||||||
|
onAddImage={handleImageUpload}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -377,8 +377,9 @@ export default function GroceryList() {
|
|||||||
<GroceryListItem
|
<GroceryListItem
|
||||||
key={item.id}
|
key={item.id}
|
||||||
item={item}
|
item={item}
|
||||||
onClick={(quantity) =>
|
allItems={sortedItems}
|
||||||
[ROLES.ADMIN, ROLES.EDITOR].includes(role) && handleBought(item.id, quantity)
|
onClick={(id, quantity) =>
|
||||||
|
[ROLES.ADMIN, ROLES.EDITOR].includes(role) && handleBought(id, quantity)
|
||||||
}
|
}
|
||||||
onImageAdded={
|
onImageAdded={
|
||||||
[ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleImageAdded : null
|
[ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleImageAdded : null
|
||||||
@ -398,8 +399,9 @@ export default function GroceryList() {
|
|||||||
<GroceryListItem
|
<GroceryListItem
|
||||||
key={item.id}
|
key={item.id}
|
||||||
item={item}
|
item={item}
|
||||||
onClick={(quantity) =>
|
allItems={sortedItems}
|
||||||
[ROLES.ADMIN, ROLES.EDITOR].includes(role) && handleBought(item.id, quantity)
|
onClick={(id, quantity) =>
|
||||||
|
[ROLES.ADMIN, ROLES.EDITOR].includes(role) && handleBought(id, quantity)
|
||||||
}
|
}
|
||||||
onImageAdded={
|
onImageAdded={
|
||||||
[ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleImageAdded : null
|
[ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleImageAdded : null
|
||||||
@ -420,6 +422,7 @@ export default function GroceryList() {
|
|||||||
<GroceryListItem
|
<GroceryListItem
|
||||||
key={item.id}
|
key={item.id}
|
||||||
item={item}
|
item={item}
|
||||||
|
allItems={recentlyBoughtItems}
|
||||||
onClick={null}
|
onClick={null}
|
||||||
onImageAdded={
|
onImageAdded={
|
||||||
[ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleImageAdded : null
|
[ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleImageAdded : null
|
||||||
@ -475,6 +478,7 @@ export default function GroceryList() {
|
|||||||
item={editingItem}
|
item={editingItem}
|
||||||
onSave={handleEditSave}
|
onSave={handleEditSave}
|
||||||
onCancel={handleEditCancel}
|
onCancel={handleEditCancel}
|
||||||
|
onImageUpdate={handleImageAdded}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
.confirm-buy-modal {
|
.confirm-buy-modal {
|
||||||
background: white;
|
background: white;
|
||||||
padding: 2em;
|
padding: 1em;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
max-width: 450px;
|
max-width: 450px;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
@ -22,47 +22,107 @@
|
|||||||
animation: slideUp 0.3s ease-out;
|
animation: slideUp 0.3s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm-buy-modal h2 {
|
.confirm-buy-header {
|
||||||
margin: 0 0 0.5em 0;
|
|
||||||
font-size: 1.5em;
|
|
||||||
color: #333;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-zone {
|
||||||
|
font-size: 0.85em;
|
||||||
|
color: #666;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 0.2em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm-buy-item-name {
|
.confirm-buy-item-name {
|
||||||
margin: 0 0 1.5em 0;
|
margin: 0;
|
||||||
font-size: 1.1em;
|
font-size: 1.2em;
|
||||||
color: #007bff;
|
color: #007bff;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
text-align: center;
|
}
|
||||||
|
|
||||||
|
.confirm-buy-image-section {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.6em;
|
||||||
|
margin: 0.8em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-nav-btn {
|
||||||
|
width: 35px;
|
||||||
|
height: 35px;
|
||||||
|
border: 2px solid #007bff;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: white;
|
||||||
|
color: #007bff;
|
||||||
|
font-size: 1.8em;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
line-height: 1;
|
||||||
|
padding: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-nav-btn:hover:not(:disabled) {
|
||||||
|
background: #007bff;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-nav-btn:disabled {
|
||||||
|
border-color: #ccc;
|
||||||
|
color: #ccc;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-image-container {
|
||||||
|
width: 280px;
|
||||||
|
height: 280px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 2px solid #ddd;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-image {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-image-placeholder {
|
||||||
|
font-size: 4em;
|
||||||
|
color: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm-buy-quantity-section {
|
.confirm-buy-quantity-section {
|
||||||
margin: 2em 0;
|
margin: 0.8em 0;
|
||||||
}
|
|
||||||
|
|
||||||
.confirm-buy-label {
|
|
||||||
margin: 0 0 1em 0;
|
|
||||||
font-size: 1em;
|
|
||||||
color: #555;
|
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm-buy-counter {
|
.confirm-buy-counter {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 1em;
|
gap: 0.8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm-buy-counter-btn {
|
.confirm-buy-counter-btn {
|
||||||
width: 50px;
|
width: 45px;
|
||||||
height: 50px;
|
height: 45px;
|
||||||
border: 2px solid #007bff;
|
border: 2px solid #007bff;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: white;
|
background: white;
|
||||||
color: #007bff;
|
color: #007bff;
|
||||||
font-size: 1.8em;
|
font-size: 1.6em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
@ -85,12 +145,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.confirm-buy-counter-display {
|
.confirm-buy-counter-display {
|
||||||
width: 80px;
|
width: 70px;
|
||||||
height: 50px;
|
height: 45px;
|
||||||
border: 2px solid #ddd;
|
border: 2px solid #ddd;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 1.5em;
|
font-size: 1.4em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #333;
|
color: #333;
|
||||||
background: #f8f9fa;
|
background: #f8f9fa;
|
||||||
@ -103,20 +163,21 @@
|
|||||||
|
|
||||||
.confirm-buy-actions {
|
.confirm-buy-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 1em;
|
gap: 0.6em;
|
||||||
margin-top: 2em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm-buy-cancel,
|
.confirm-buy-cancel,
|
||||||
.confirm-buy-confirm {
|
.confirm-buy-confirm {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 0.9em;
|
padding: 0.75em 0.5em;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
font-size: 1em;
|
font-size: 0.95em;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm-buy-cancel {
|
.confirm-buy-cancel {
|
||||||
@ -156,3 +217,88 @@
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mobile optimizations */
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.confirm-buy-modal {
|
||||||
|
padding: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-header {
|
||||||
|
margin-bottom: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-zone {
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-item-name {
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-image-section {
|
||||||
|
gap: 0.5em;
|
||||||
|
margin: 0.6em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-actions {
|
||||||
|
gap: 0.5em;
|
||||||
|
margin-top: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-cancel,
|
||||||
|
.confirm-buy-confirm {
|
||||||
|
padding: 0.7em 0.4em;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-image-container {
|
||||||
|
width: 220px;
|
||||||
|
height: 220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-nav-btn {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
font-size: 1.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-counter-btn {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
font-size: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-counter-display {
|
||||||
|
width: 60px;
|
||||||
|
height: 40px;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-quantity-section {
|
||||||
|
margin: 0.6em 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 360px) {
|
||||||
|
.confirm-buy-modal {
|
||||||
|
padding: 0.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-cancel,
|
||||||
|
.confirm-buy-confirm {
|
||||||
|
padding: 0.65em 0.3em;
|
||||||
|
font-size: 0.85em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-image-container {
|
||||||
|
width: 180px;
|
||||||
|
height: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-buy-nav-btn {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
font-size: 1.4em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -110,3 +110,26 @@
|
|||||||
.edit-modal-btn-save:hover:not(:disabled) {
|
.edit-modal-btn-save:hover:not(:disabled) {
|
||||||
background: #0056b3;
|
background: #0056b3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.edit-modal-btn-image {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.7em;
|
||||||
|
font-size: 1em;
|
||||||
|
border: 2px solid #28a745;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: all 0.2s;
|
||||||
|
background: white;
|
||||||
|
color: #28a745;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-modal-btn-image:hover:not(:disabled) {
|
||||||
|
background: #28a745;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-modal-btn-image:disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user