diff --git a/src/hospitality-web/src/pages/admin/EventDetailPage.tsx b/src/hospitality-web/src/pages/admin/EventDetailPage.tsx index 128b4ac..56ba582 100644 --- a/src/hospitality-web/src/pages/admin/EventDetailPage.tsx +++ b/src/hospitality-web/src/pages/admin/EventDetailPage.tsx @@ -1,5 +1,6 @@ import { useState } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; +import { Card, Button, Row, Col, Form, Modal } from 'react-bootstrap'; import { useEvent } from '../../hooks/useEvents'; import { useGroups, useCreateGroup } from '../../hooks/useGroups'; import { useProducts, useCreateProduct } from '../../hooks/useProducts'; @@ -14,8 +15,8 @@ export default function EventDetailPage() { const createGroup = useCreateGroup(id!); const createProduct = useCreateProduct(id!); - const [showGroupForm, setShowGroupForm] = useState(false); - const [showProductForm, setShowProductForm] = useState(false); + const [showGroupModal, setShowGroupModal] = useState(false); + const [showProductModal, setShowProductModal] = useState(false); const [groupForm, setGroupForm] = useState({ name: '' }); const [productForm, setProductForm] = useState({ name: '', type: ProductType.Drink }); @@ -23,143 +24,173 @@ export default function EventDetailPage() { e.preventDefault(); await createGroup.mutateAsync(groupForm); setGroupForm({ name: '' }); - setShowGroupForm(false); + setShowGroupModal(false); }; const handleCreateProduct = async (e: React.FormEvent) => { e.preventDefault(); await createProduct.mutateAsync(productForm); setProductForm({ name: '', type: ProductType.Drink }); - setShowProductForm(false); + setShowProductModal(false); }; - if (!event) return
Loading...
; + if (!event) return
Loading...
; return ( -
-
-

{event.name}

-

{event.location}

+ <> +
+

{event.name}

+

{event.location}

+

+ {new Date(event.startDate).toLocaleDateString()} - {new Date(event.endDate).toLocaleDateString()} +

-
- {/* Groups Section */} -
-
-

Groups

- -
- - {showGroupForm && ( -
-
- setGroupForm({ ...groupForm, name: e.target.value })} - className="w-full px-3 py-2 border border-gray-300 rounded-lg" - /> - setGroupForm({ ...groupForm, contactPersonName: e.target.value })} - className="w-full px-3 py-2 border border-gray-300 rounded-lg" - /> - setGroupForm({ ...groupForm, contactEmail: e.target.value })} - className="w-full px-3 py-2 border border-gray-300 rounded-lg" - /> - -
-
- )} - -
- {groups?.map((group) => ( -
navigate(`/groups/${group.id}`)} - className="bg-white p-4 rounded-lg shadow cursor-pointer hover:shadow-lg transition-shadow" - > -

{group.name}

- {group.contactPersonName && ( -

{group.contactPersonName}

+ + + + +
Groups
+ +
+ +
+ {groups?.map((group) => ( + navigate(`/groups/${group.id}`)} + > + +
{group.name}
+ {group.contactPersonName && ( + {group.contactPersonName} + )} + {group.peopleCount || 0} people +
+
+ ))} + {(!groups || groups.length === 0) && ( +

No groups yet

)} -

{group.peopleCount || 0} people

- ))} -
-
+ + + - {/* Products Section */} -
-
-

Products

- -
+ + + +
Products
+ +
+ +
+ {products?.map((product) => ( + + +
{product.name}
+ {ProductType[product.type]} +
+
+ ))} + {(!products || products.length === 0) && ( +

No products yet

+ )} +
+
+
+ + - {showProductForm && ( -
-
- setProductForm({ ...productForm, name: e.target.value })} - className="w-full px-3 py-2 border border-gray-300 rounded-lg" - /> - - -
+ {/* Group Modal */} + setShowGroupModal(false)}> + + Add Group + + +
+ + Group Name + setGroupForm({ ...groupForm, name: e.target.value })} + /> + + + Contact Person (optional) + setGroupForm({ ...groupForm, contactPersonName: e.target.value })} + /> + + + Contact Email (optional) + setGroupForm({ ...groupForm, contactEmail: e.target.value })} + /> + +
+ +
- )} +
+
+
-
- {products?.map((product) => ( -
-

{product.name}

-

{ProductType[product.type]}

-
- ))} -
-
-
-
+ {/* Product Modal */} + setShowProductModal(false)}> + + Add Product + + +
+ + Product Name + setProductForm({ ...productForm, name: e.target.value })} + /> + + + Product Type + setProductForm({ ...productForm, type: parseInt(e.target.value) })} + > + + + + + + +
+ + +
+
+
+
+ ); } diff --git a/src/hospitality-web/src/pages/admin/GroupDetailPage.tsx b/src/hospitality-web/src/pages/admin/GroupDetailPage.tsx index c597ca8..39dedbf 100644 --- a/src/hospitality-web/src/pages/admin/GroupDetailPage.tsx +++ b/src/hospitality-web/src/pages/admin/GroupDetailPage.tsx @@ -1,5 +1,6 @@ import { useState } from 'react'; import { useParams } from 'react-router-dom'; +import { Card, Button, Form, Modal, ListGroup, Badge, Row, Col } from 'react-bootstrap'; import { useGroup, useCreatePerson, useAssignQuota } from '../../hooks/useGroups'; import { useProducts } from '../../hooks/useProducts'; import type { CreatePersonRequest, Person } from '../../lib/types'; @@ -10,13 +11,12 @@ export default function GroupDetailPage() { const createPerson = useCreatePerson(id!); const assignQuota = useAssignQuota(); - const [showPersonForm, setShowPersonForm] = useState(false); + const [showPersonModal, setShowPersonModal] = useState(false); const [personForm, setPersonForm] = useState({ name: '' }); const [selectedPerson, setSelectedPerson] = useState(null); const [quotaProductId, setQuotaProductId] = useState(''); const [quotaAmount, setQuotaAmount] = useState(1); - // Get event ID from group data const eventId = group?.eventId || ''; const { data: products } = useProducts(eventId); @@ -24,7 +24,7 @@ export default function GroupDetailPage() { e.preventDefault(); await createPerson.mutateAsync(personForm); setPersonForm({ name: '' }); - setShowPersonForm(false); + setShowPersonModal(false); refetch(); }; @@ -42,160 +42,169 @@ export default function GroupDetailPage() { alert('Quota assigned successfully!'); setQuotaProductId(''); setQuotaAmount(1); + setSelectedPerson(null); refetch(); } catch (error) { alert('Failed to assign quota'); } }; - if (!group) return
Loading...
; + if (!group) return
Loading...
; return ( -
-
-

{group.name}

+ <> +
+

{group.name}

{group.contactPersonName && ( -

Contact: {group.contactPersonName}

+

Contact: {group.contactPersonName}

)} {group.contactEmail && ( -

{group.contactEmail}

+

{group.contactEmail}

)}
-
-

People ({group.people?.length || 0})

- +
+

People ({group.people?.length || 0})

+
- {showPersonForm && ( -
-

Add New Person

-
-
- - + {group.people?.map((person) => ( + + + +
+
+
{person.name}
+ {person.email && {person.email}} + {person.phoneNumber && {person.phoneNumber}} + + QR: {person.qrCode.substring(0, 8)}... + +
+ +
+ + {person.quotas && person.quotas.length > 0 && ( +
+
Current Quotas
+ + {person.quotas.map((quota) => ( + + {quota.productName} + {quota.remainingAmount}/{quota.initialAmount} + + ))} + +
+ )} + + {selectedPerson?.id === person.id && ( +
+
Assign New Quota
+ + setQuotaProductId(e.target.value)} + > + + {products?.map((product) => ( + + ))} + + + + setQuotaAmount(parseInt(e.target.value))} + placeholder="Amount" + /> + + +
+ )} +
+
+ + ))} + + + {(!group.people || group.people.length === 0) && ( + + +

No people in this group yet.

+ +
+
+ )} + + {/* Add Person Modal */} + setShowPersonModal(false)}> + + Add Person + + + + + Name * + setPersonForm({ ...personForm, name: e.target.value })} - className="w-full px-3 py-2 border border-gray-300 rounded-lg" /> -
-
- - + + Email + setPersonForm({ ...personForm, email: e.target.value })} - className="w-full px-3 py-2 border border-gray-300 rounded-lg" /> -
-
- - + + Phone Number + setPersonForm({ ...personForm, phoneNumber: e.target.value })} - className="w-full px-3 py-2 border border-gray-300 rounded-lg" /> + +
+ +
- - -
- )} - -
- {group.people?.map((person) => ( -
-
-
-

{person.name}

- {person.email &&

{person.email}

} - {person.phoneNumber &&

{person.phoneNumber}

} -

QR: {person.qrCode}

-
- -
- - {person.quotas && person.quotas.length > 0 && ( -
-

Current Quotas

-
- {person.quotas.map((quota) => ( -
- {quota.productName} - {quota.remainingAmount}/{quota.initialAmount} -
- ))} -
-
- )} - - {selectedPerson?.id === person.id && ( -
-

Assign New Quota

-
- - setQuotaAmount(parseInt(e.target.value))} - placeholder="Amount" - className="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm" - /> - -
-
- )} -
- ))} -
- - {(!group.people || group.people.length === 0) && !showPersonForm && ( -
-

No people in this group yet.

- -
- )} -
+ + + + ); }