diff --git a/src/components/Admin/AdminMemberCard.tsx b/src/components/Admin/AdminMemberCard.tsx new file mode 100644 index 0000000..14f32ce --- /dev/null +++ b/src/components/Admin/AdminMemberCard.tsx @@ -0,0 +1,229 @@ +import { color, h2_, h4, h6, h6_, titleColor } from '@/constants'; +import { Backdrop, Box, Typography, Button, Modal, TextField, useMediaQuery } from '@mui/material'; +import { useState } from 'react'; +import { MemberDatatype } from '@/data/members'; + +interface AdminMemberCardProps { + adminName: string; + adminRole: string; + adminDescription: string; + adminThumbnail: string; + onDelete: () => void; + onEdit: (updatedAdmin: Partial) => void; +} + +const AdminMemberCard = ({ + adminName, + adminRole, + adminDescription, + adminThumbnail, + onDelete, + onEdit, +}: AdminMemberCardProps) => { + const breakPoint = useMediaQuery('(min-width:600px)'); + const [isClicked, setIsClicked] = useState(false); + const [mouseOver, setMouseOver] = useState(false); + const [isEditModalOpen, setIsEditModalOpen] = useState(false); + + // Temporary state for editing. These keys are temporary. + const [editedAdmin, setEditedAdmin] = useState({ + name: adminName, + role: adminRole, + thumbnail: '', // This will map to memberImage + description: adminDescription, + }); + + function handleClick() { + setIsClicked(!isClicked); + } + + function handleEditSave() { + // Map the temporary keys to MemberDatatype keys + onEdit({ + memberName: editedAdmin.name, + memberRole: editedAdmin.role, + memberImage: editedAdmin.thumbnail, // if thumbnail is provided, it updates memberImage + memberQuote: editedAdmin.description, + }); + setIsEditModalOpen(false); + } + + return ( + <> + setMouseOver(true)} + onMouseLeave={() => setMouseOver(false)} + > + theme.zIndex.drawer + 2, + backgroundColor: 'black', + display: 'flex', + fontSize: '30px', + padding: '20px', + flexDirection: breakPoint ? 'row' : 'column', + gap: '20px', + }} + open={isClicked} + > + + + + {adminName} + + + {adminRole} + + + {adminDescription} + + + + + admin image + + + + {adminName} + + + {adminRole} + + + + + + + + + setIsEditModalOpen(false)}> + + + Edit Admin + + + setEditedAdmin((prev) => ({ ...prev, name: e.target.value })) + } + margin="normal" + /> + + setEditedAdmin((prev) => ({ ...prev, role: e.target.value })) + } + margin="normal" + /> + + setEditedAdmin((prev) => ({ ...prev, thumbnail: e.target.value })) + } + margin="normal" + /> + + setEditedAdmin((prev) => ({ ...prev, description: e.target.value })) + } + margin="normal" + /> + + + + + + + + ); +}; + +export default AdminMemberCard; diff --git a/src/components/Member/MemberCard.tsx b/src/components/Member/MemberCard.tsx index d38380c..14dcf7d 100644 --- a/src/components/Member/MemberCard.tsx +++ b/src/components/Member/MemberCard.tsx @@ -131,3 +131,400 @@ const MemberCard = ({ }; export default MemberCard; + +// import { color, h2_, h4, h6, h6_, titleColor } from '@/constants'; +// import { Backdrop, Box, Typography, Button, Modal, TextField, useMediaQuery } from '@mui/material'; +// import { useState } from 'react'; + +// interface MemberCardProps { +// memberName: string; +// memberRole: string; +// memberThumbnail: string; +// memberDescription: string; +// key: number; +// } + +// const MemberCard = ({ +// memberName, +// memberRole, +// memberThumbnail, +// memberDescription, +// }: MemberCardProps) => { +// const breakPoint = useMediaQuery('(min-width:600px)'); +// const [isClicked, setIsClicked] = useState(false); +// const [mouseOver, setMouseOver] = useState(false); +// const [isEditModalOpen, setIsEditModalOpen] = useState(false); +// const [editedMember, setEditedMember] = useState({ +// name: memberName, +// role: memberRole, +// thumbnail: memberThumbnail, +// description: memberDescription, +// }); + +// function handleClick() { +// setIsClicked(!isClicked); +// } + +// return ( +// <> +// setMouseOver(true)} +// onMouseLeave={() => setMouseOver(false)} +// > +// theme.zIndex.drawer + 2, +// backgroundColor: 'black', +// display: 'flex', +// fontSize: '30px', +// padding: '20px', +// flexDirection: breakPoint ? 'row' : 'column', +// gap: '20px', +// }} +// className="closeIconCursor" +// open={isClicked} +// > +// +// +// +// {memberName} +// + +// +// {memberRole} +// + +// +// {memberDescription} +// +// +// +// +// drone image +// +// +// +// {memberName} +// +// +// {memberRole} +// + +// {/* Edit and Delete buttons placed at the bottom */} +// +// +// +// +// ); +// }; + +// export default MemberCard; + + + +// // import { color, h2_, h4, h6, h6_, titleColor } from '@/constants'; +// // import { Backdrop, Box, Typography, Button, TextField, useMediaQuery } from '@mui/material'; +// // import { useState } from 'react'; + +// // interface MemberCardProps { +// // memberName: string; +// // memberRole: string; +// // memberThumbnail: string; +// // memberDescription: string; +// // key: number; +// // onEdit: (updatedMember: any) => void; +// // onDelete: () => void; +// // } + +// // const MemberCard = ({ +// // memberName, +// // memberRole, +// // memberThumbnail, +// // memberDescription, +// // onEdit, +// // onDelete, +// // }: MemberCardProps) => { +// // const breakPoint = useMediaQuery('(min-width:600px)'); +// // const [isClicked, setIsClicked] = useState(false); +// // const [mouseOver, setMouseOver] = useState(false); +// // const [isEditing, setIsEditing] = useState(false); +// // const [editData, setEditData] = useState({ +// // memberName, +// // memberRole, +// // memberThumbnail, +// // memberDescription, +// // }); + +// // const handleClick = () => { +// // setIsClicked(!isClicked); +// // }; + +// // const handleEditClick = () => { +// // setIsEditing(true); +// // }; + +// // const handleSaveClick = () => { +// // onEdit(editData); // Update the member details +// // setIsEditing(false); +// // }; + +// // const handleCancelClick = () => { +// // setEditData({ +// // memberName, +// // memberRole, +// // memberThumbnail, +// // memberDescription, +// // }); +// // setIsEditing(false); +// // }; + +// // const handleInputChange = (e: React.ChangeEvent) => { +// // setEditData({ +// // ...editData, +// // [e.target.name]: e.target.value, +// // }); +// // }; + +// // return ( +// // <> +// // setMouseOver(true)} +// // onMouseLeave={() => setMouseOver(false)} +// // > +// // +// // +// // {memberName} +// // +// // +// // {memberRole} +// // +// // +// // +// // +// // +// // +// // drone image +// // + +// // {/* Editable Form Overlay */} +// // {isEditing && ( +// // theme.zIndex.drawer + 2, +// // backgroundColor: 'rgba(0, 0, 0, 0.5)', // Blurred background +// // display: 'flex', +// // justifyContent: 'center', +// // alignItems: 'center', +// // }} +// // > +// // +// // +// // Edit Member Information +// // + +// // +// // +// // +// // + +// // +// // +// // +// // +// // +// // +// // )} +// // +// // ); +// // }; + +// // export default MemberCard; + + + + + diff --git a/src/components/Member/members.tsx b/src/components/Member/members.tsx index a42b1fc..4e3b1cb 100644 --- a/src/components/Member/members.tsx +++ b/src/components/Member/members.tsx @@ -1,12 +1,45 @@ +import { useEffect, useState } from 'react'; import MemberCard from '@/components/Member/MemberCard'; import { color, h4, h5 } from '@/constants'; import { Box, Typography, useMediaQuery } from '@mui/material'; -import MemberData from '@/data/members'; +import MemberData, { MemberDatatype } from '@/data/members'; +import { getDocs, getDocsFromCache, collection } from 'firebase/firestore'; +import { db } from '@/firebase'; export default function Members() { const breakPoint = useMediaQuery('(min-width:600px)'); const breakPoint2 = useMediaQuery('(min-width:750px)'); + const [members, setMembers] = useState(MemberData); + + useEffect(() => { + async function fetchMembers() { + const res = await getDocsFromCache(collection(db, 'members')); + if (!res.empty) { + const memberData = res.docs.map((doc) => doc.data() as MemberDatatype); + setMembers(memberData); + } + else { + const res = await getDocs(collection(db, 'members')); + if (!res.empty) { + // const memberData = res.docs.map((doc) => doc.data() as MemberDatatype); + const memberData = res.docs.map((doc) => { + const data = doc.data() + return { + memberName: data.name, + memberRole: data.role, + memberQuote: data.quote, + memberImage: data.image + } as MemberDatatype + }); + // console.log(memberData); + setMembers(memberData); + } + } + } + fetchMembers(); + }, []); + return ( - {MemberData.map((member, index) => ( + {members.map((member, index) => ( ))} ); } +// src/pages/members.tsx + +// import MemberCard from '@/components/Member/MemberCard'; +// import { color, h4, h5 } from '@/constants'; +// import { Box, Typography, useMediaQuery, Button, Modal, TextField } from '@mui/material'; +// import MemberData from '@/data/members'; +// import { useState } from 'react'; + +// export default function Members() { +// const breakPoint = useMediaQuery('(min-width:600px)'); +// const breakPoint2 = useMediaQuery('(min-width:750px)'); +// const [members, setMembers] = useState(MemberData); +// const [isAddModalOpen, setIsAddModalOpen] = useState(false); +// const [newMember, setNewMember] = useState({ +// name: '', +// role: '', +// thumbnail: '', +// description: '' +// }); + +// // function handleDelete(index: number) { +// // setMembers(members.filter((_, i) => i !== index)); +// // } + +// // function handleEdit(index: number, updatedMember: Partial) { +// // const updatedMembers = [...members]; +// // updatedMembers[index] = { ...updatedMembers[index], ...updatedMember }; +// // setMembers(updatedMembers); +// // } + +// // function handleAddMember() { +// // setMembers([ +// // ...members, +// // { +// // memberName: newMember.name, +// // memberRole: newMember.role, +// // memberThumbnail: newMember.thumbnail, +// // memberQuote: newMember.description +// // } +// // ]); +// // setIsAddModalOpen(false); +// // setNewMember({ name: '', role: '', thumbnail: '', description: '' }); +// // } + +// return ( +// +// +// Members +// + +// {/* Add Member Button */} +// {/* */} + +// +// {members.map((member, index) => ( +// +// // onDelete={() => handleDelete(index)} +// // onEdit={(updatedMember) => handleEdit(index, updatedMember)} +// ))} +// + +// {/* Add Member Modal */} +// setIsAddModalOpen(false)}> +// +// +// Add New Member +// +// +// setNewMember((prev) => ({ ...prev, name: e.target.value })) +// } +// margin="normal" +// /> +// +// setNewMember((prev) => ({ ...prev, role: e.target.value })) +// } +// margin="normal" +// /> +// +// setNewMember((prev) => ({ ...prev, thumbnail: e.target.value })) +// } +// margin="normal" +// /> +// +// setNewMember((prev) => ({ ...prev, description: e.target.value })) +// } +// margin="normal" +// /> +// +// {/* +// */} +// +// +// +// +// ); +// } diff --git a/src/data/members.ts b/src/data/members.ts index 2dd3365..3fae6da 100644 --- a/src/data/members.ts +++ b/src/data/members.ts @@ -1,8 +1,8 @@ export interface MemberDatatype { + docId?: string; memberName: string; memberRole: string; memberQuote: string; - memberYear?: string; memberImage?: string; } diff --git a/src/pages/admin/members/index.tsx b/src/pages/admin/members/index.tsx new file mode 100644 index 0000000..0e6f693 --- /dev/null +++ b/src/pages/admin/members/index.tsx @@ -0,0 +1,214 @@ +import { useState, useEffect } from 'react'; +import { Box, Typography, useMediaQuery, Button, Modal, TextField } from '@mui/material'; +import { color, h4, h5 } from '@/constants'; +import MemberData, { MemberDatatype } from '@/data/members'; +import AdminMemberCard from '@/components/Admin/AdminMemberCard'; +import { getDocs, getDocsFromCache, collection, addDoc, deleteDoc, doc, updateDoc } from 'firebase/firestore'; +import { db } from '@/firebase'; + + +export default function Members() { + const breakPoint = useMediaQuery('(min-width:600px)'); + const breakPoint2 = useMediaQuery('(min-width:750px)'); + + const [members, setMembers] = useState(MemberData); + + useEffect(() => { + async function fetchMembers() { + const res = await getDocsFromCache(collection(db, 'members')); + if (!res.empty) { + const memberData = res.docs.map((doc) => ({ + ...doc.data() as MemberDatatype, + docId: doc.id + })); + setMembers(memberData); + } + else { + const res = await getDocs(collection(db, 'members')); + if (!res.empty) { + const memberData = res.docs.map((doc) => { + const data = doc.data() + return { + docId: doc.id, + memberName: data.name, + memberRole: data.role, + memberQuote: data.quote, + memberImage: data.image + } as MemberDatatype + }); + setMembers(memberData); + } + } + } + fetchMembers(); + }, []); + + const [isAddModalOpen, setIsAddModalOpen] = useState(false); + const [newMember, setNewMember] = useState({ + memberName: '', + memberRole: '', + memberImage: '', + memberQuote: '' + }); + + async function handleDelete(docId: string) { + try { + await deleteDoc(doc(db, 'members', docId)); + setMembers(members.filter((member) => member.docId !== docId)); + } catch (error) { + console.error('Error deleting member:', error); + } + } + + async function handleEdit(docId: string, updatedMember: Partial) { + try { + const memberRef = doc(db, 'members', docId); + await updateDoc(memberRef, { + name: updatedMember.memberName, + role: updatedMember.memberRole, + quote: updatedMember.memberQuote, + image: updatedMember.memberImage + }); + setMembers((prevMembers) => + prevMembers.map((member) => + member.docId === docId ? { ...member, ...updatedMember } : member + ) + ); + } catch (error) { + console.error('Error updating member:', error); + } + } + + async function handleAddMember() { + try { + const membersRef = collection(db, 'members'); + const docRef = await addDoc(membersRef, { + name: newMember.memberName, + role: newMember.memberRole, + quote: newMember.memberQuote, + image: newMember.memberImage + }); + setMembers((prevMembers) => [ + ...prevMembers, + { + docId: docRef.id, + memberName: newMember.memberName, + memberRole: newMember.memberRole, + memberImage: newMember.memberImage, + memberQuote: newMember.memberQuote + } + ]); + setIsAddModalOpen(false); + setNewMember({ memberName: '', memberRole: '', memberImage: '', memberQuote: '' }); + } catch (error) { + console.error('Error adding member:', error); + } + } + + return ( + + + + Admin Members + + + {/* Add Member Button */} + + + + {members.map((member) => ( + handleDelete(member.docId!)} + onEdit={(updatedMember) => handleEdit(member.docId!, updatedMember)} + /> + ))} + + + {/* Add Member Modal */} + setIsAddModalOpen(false)}> + + + Add New Member + + + setNewMember((prev) => ({ ...prev, memberName: e.target.value })) + } + margin="normal" + /> + + setNewMember((prev) => ({ ...prev, memberRole: e.target.value })) + } + margin="normal" + /> + + setNewMember((prev) => ({ ...prev, memberImage: e.target.value })) + } + margin="normal" + /> + + setNewMember((prev) => ({ ...prev, memberQuote: e.target.value })) + } + margin="normal" + /> + + + + + + + + + ); +}