@@ -30,14 +30,19 @@ const SetPaymentQr = ({ cafeId }) => {
const [ loading , setLoading ] = useState ( true ) ;
const [ error , setError ] = useState ( null ) ;
const [ showForm , setShowForm ] = useState ( false ) ;
const [ selectedMaterialId , setSelectedMaterialId ] = useState ( null ) ;
const [ selectedMaterialIndex , setSelectedMaterialIndex ] = useState ( - 1 ) ;
const [ latestMutation , setLatestMutation ] = useState ( [ ] ) ;
const [ currentQuantity , setCurrentQuantity ] = useState ( - 1 ) ;
const [ currentPrice , setCurrentPrice ] = useState ( 0 ) ;
const [ quantityChange , setQuantityChange ] = useState ( 0 ) ;
const [ sortOrder , setSortOrder ] = useState ( "desc" ) ;
const [ isEditCurrentPrice , setIsEditCurrentPrice ] = useState ( false ) ;
const [ isViewingHistory , setIsViewingHistory ] = useState ( false ) ;
const convertToInteger = ( formattedValue ) => {
// Remove dots and convert to integer
return parseInt ( formattedValue . replace ( /\./g , "" ) , 10 ) ;
} ;
const formatCurrency = ( value ) => {
if ( ! value ) return "" ;
@@ -53,12 +58,14 @@ const SetPaymentQr = ({ cafeId }) => {
useEffect ( ( ) => {
const fetchMaterials = async ( ) => {
setLoading ( true ) ;
try {
const data = await getMaterials ( cafeId ) ;
setMaterials ( data ) ;
console . log ( data )
setError ( null ) ;
if ( data . length > 0 ) {
setSelectedMaterialIndex ( 0 ) ;
}
} catch ( error ) {
console . error ( "Error fetching materials:" , error ) ;
setError ( "Failed to fetch materials." ) ;
@@ -69,9 +76,6 @@ const SetPaymentQr = ({ cafeId }) => {
try {
const data = await getMaterialMutations ( cafeId ) ;
setMutations ( data ) ;
if ( data . length > 0 ) {
setSelectedMaterialId ( 0 ) ;
}
} catch ( err ) {
setError ( err . message ) ;
} finally {
@@ -82,17 +86,15 @@ const SetPaymentQr = ({ cafeId }) => {
fetchMaterials ( ) ;
fetchMutations ( ) ;
} , [ cafeId ] ) ;
const handleSortChange = ( e ) => {
setSortOrder ( e . target . value ) ;
} ;
const filteredMutations = selectedMaterialId
? mutations . filter ( ( mutation ) => mutation . materialId === selectedMaterialId )
: [ ] ;
const filteredMutations = mutations . filter ( ( mutation ) => mutation . materialId === materials [ selectedMaterialIndex ] . materialId ) || [ ] ;
const sortedMutations = filteredMutations
. filter ( ( mutation ) => mutation . materialId === selectedM aterialId)
. filter ( ( mutation ) => mutation . materialId === materials [ selectedMaterialIndex ] . m aterialId)
. sort ( ( a , b ) => {
if ( sortOrder === "asc" ) {
return new Date ( a . createdAt ) - new Date ( b . createdAt ) ;
@@ -122,7 +124,7 @@ const SetPaymentQr = ({ cafeId }) => {
setMaterials ( data ) ;
setError ( null ) ;
if ( data . length > 0 ) {
setSelectedMaterialId ( 0 ) ;
setSelectedMaterialIndex ( 0 ) ;
}
} catch ( error ) {
console . error ( "Error creating material:" , error ) ;
@@ -141,8 +143,8 @@ const SetPaymentQr = ({ cafeId }) => {
) ;
setMaterials ( updatedMaterials ) ;
setError ( null ) ;
if ( selectedMaterialId === materialId ) {
setSelectedMaterialId (
if ( selectedMaterialIndex === materialId ) {
setSelectedMaterialIndex (
updatedMaterials . length > 0 ? updatedMaterials [ 0 ] . materialId : null
) ;
}
@@ -155,25 +157,25 @@ const SetPaymentQr = ({ cafeId }) => {
} ;
const handlePrevious = ( ) => {
if ( selectedMaterialId ) {
if ( selectedMaterialIndex ) {
setQuantityChange ( 0 ) ;
const currentIndex = materials . findIndex (
( material ) => material . materialId === selectedMaterialId
( material ) => material . materialId === selectedMaterialIndex
) ;
if ( currentIndex > 0 ) {
setSelectedMaterialId ( materials [ currentIndex - 1 ] . materialId ) ;
setSelectedMaterialIndex ( materials [ currentIndex - 1 ] . materialId ) ;
}
}
} ;
const handleNext = ( ) => {
if ( selectedMaterialId ) {
if ( selectedMaterialIndex ) {
setQuantityChange ( 0 ) ;
const currentIndex = materials . findIndex (
( material ) => material . materialId === selectedMaterialId
( material ) => material . materialId === selectedMaterialIndex
) ;
if ( currentIndex < materials . length - 1 ) {
setSelectedMaterialId ( materials [ currentIndex + 1 ] . materialId ) ;
setSelectedMaterialIndex ( materials [ currentIndex + 1 ] . materialId ) ;
}
}
} ;
@@ -184,10 +186,9 @@ const SetPaymentQr = ({ cafeId }) => {
useEffect ( ( ) => {
setQuantityChange ( 0 ) ;
console . log ( selectedMaterialId )
if ( selectedMaterialId > - 1 ) {
if ( materials . length > 0 || selectedMaterialIndex > - 1 ) {
const materialMutations = mutations . filter (
( mutation ) => mutation . materialId === materials [ selectedMaterialId ] ? . materialId
( mutation ) => mutation . materialId === materials [ selectedMaterialIndex ] ? . materialId
) ;
console . log ( materialMutations )
if ( materialMutations . length > 0 ) {
@@ -203,40 +204,40 @@ const SetPaymentQr = ({ cafeId }) => {
setCurrentPrice ( formatCurrency ( latestMutation . priceAtp ) ) ;
} else {
setCurrentQuantity ( 0 ) ; // Default value if no mutations exist
setLatestMutation ( { newStock : 0 } ) ;
setLatestMutation ( { newStock : 0 } ) ;
setCurrentPrice ( 0 ) ;
}
}
} , [ selectedMaterialId ] ) ;
} , [ materials , mutations , selectedMaterialIndex ] ) ;
const handleUpdateStock = async ( ) => {
if ( selectedMaterialId ) {
setLoading ( true ) ;
try {
const newStock = currentQuantity + quantityChange ;
const formData = new FormData ( ) ;
formData . append ( "newStock" , newStock ) ;
formData . append ( "priceAtp" , current Price) ;
formData . append ( "reason" , "Stock update" ) ;
setLoading ( true ) ;
try {
const newPrice = convertToInteger ( currentPrice )
const newStock = currentQuantity + quantityChange ;
const formData = new FormData ( ) ;
formData . append ( "newStock" , newStock ) ;
formData . append ( "priceAtp" , new Price) ;
formData . append ( "reason" , "Stock update" ) ;
await createMaterialMutation ( selectedM aterialId, formData ) ;
setQuantityChange ( 0 ) ;
const updatedMutations = await getMaterialMutations ( cafeId ) ;
setMutations ( updatedMutations ) ;
setCurrentQuantity ( newStock ) ;
setError ( null ) ;
} catch ( error ) {
console . error ( "Error updating stock:" , error ) ;
setError ( "Failed to update stock." ) ;
} finally {
setLoading ( false ) ;
}
await createMaterialMutation ( materials [ selectedMaterialIndex ] . m aterialId, formData ) ;
setQuantityChange ( 0 ) ;
const updatedMutations = await getMaterialMutations ( cafeId ) ;
setMutations ( updatedMutations ) ;
setCurrentQuantity ( newStock ) ;
setError ( null ) ;
} catch ( error ) {
console . error ( "Error updating stock:" , error ) ;
setError ( "Failed to update stock." ) ;
} finally {
setLoading ( false ) ;
}
} ;
const currentMaterial = materials . find (
( material ) => material . materialId === selectedMaterialId
( material ) => material . materialId === selectedMaterialIndex
) ;
const formatDate = ( timestamp ) => {
const date = new Date ( timestamp ) ;
@@ -246,48 +247,130 @@ const SetPaymentQr = ({ cafeId }) => {
return (
< div style = { styles . container } >
< h3 style = { styles . title } > Stok < / h 3 >
<Carousel items = { materials } onSelect = { ( e ) => setSelectedMaterialId ( e ) } / >
< div style = { styles . uploadMessage } >
< p > harga per { materials && materials [ selectedMaterialId ] ? . unit } sekarang < / p >
< / d i v >
< div style = { styles . resultMessage } >
{ loading ?
< >
< / >
:
< >
< h3 style = { styles . title } > Bahan baku < / h 3 >
< Carousel items = { materials } onSelect = { ( e ) => setSelectedMaterialIndex ( e ) } selectedIndex = { selectedMaterialIndex } / >
{ selectedMaterialIndex != - 1 ?
< >
< div style = { styles . switchContainer } >
< h3 > Stok sekarang { currentQuantity } < / h 3 >
< / d i v >
< input
style = { {
width : "200px" ,
border : isEditCurrentPrice ? "1px solid #ccc" : "1px solid transparent" ,
backgroundColor : isEditCurrentPrice ? "white" : "transparent" ,
} }
disabled = { ! isEditCurrentPrice }
value = { currentPrice }
onChange = { handleChan ge}
placeholder = "Enter amount"
/ >
< div onClick = { ( ) => setIsEditCurrentPrice ( ! isEditCurrentPrice ) } style = { styles . uploadButton } > { isEditCurrentPrice ? 'Terapkan' : 'Ganti' } < / d i v >
< / d i v >
< div style = { styles . switchContainer } >
< h3 > Stok sekarang { currentQuantity } < / h 3 >
< / d i v >
< div style = { styles . stokContainer } >
< button onClick = { ( ) => handleQuantityChange ( currentQuantity + quantityChange > 0 ? - 1 : 0 ) } style = { styles . stockButton } >
-
< / b u t t o n >
< p > { currentQuantity + quantityChange } < / p >
< button onClick = { ( ) => handleQuantityChange ( 1 ) } style = { styles . stockButton } >
+
< / b u t t o n >
< / d i v >
< div style = { styles . uploadMessa ge } >
< p > harga per { materials && materials [ selectedMaterialIndex ] ? . unit } sekarang < / p >
< / d i v >
< div style = { styles . resultMessage } >
< div style = { styles . stokContainer } >
< button onClick = { ( ) => handleQuantityChange ( currentQuantity + quantityChange > 0 ? - 1 : 0 ) } style = { styles . saveButton } >
-
< / b u t t o n >
< p > { currentQuantity + quantityChange } < / p >
< button onClick = { ( ) => handleQuantityChange ( 1 ) } style = { styles . saveButton } >
+
< / b u t t o n >
< / d i v >
< div style = { styles . buttonContainer } >
< button style = { styles . saveButton } >
Laporkan { quantityChange > 0 ? 'penambahan' : 'stok sekarang' } { quantityChange < 1 ? currentQuantity + quantityChange : quantityChange } { materials [ selectedMaterialId ] ? . unit }
< / b u t t o n >
< / d i v >
< div style = { styles . history Container} >
< h3 > & gt ; Riwayat stok < / h 3 >
< / d i v >
< input
style = { {
width : "200px" ,
border : isEditCurrentPrice ? "1px solid #ccc" : "1px solid transparent" ,
backgroundColor : isEditCurrentPrice ? "white" : "transparent" ,
} }
disabled = { ! isEditCurrentPrice || quantityChange < 1 }
value = { currentPrice }
onChange = { handleChange }
placeholder = "Enter amount"
/ >
< div onClick = { ( ) => quantityChange < 1 ? null : setIsEditCurrentPrice ( ! isEditCurrentPrice ) } style = { quantityChange < 1 ? styles . changeButtonDisabled : styles . changeButtonEnabled } > { isEditCurrentPrice ? 'Terapkan' : 'Ganti' } < / d i v >
< / d i v >
< div style = { styles . button Container} >
< button onClick = { handleUpdateStock } style = { styles . saveButton } >
Laporkan { quantityChange > 0 ? 'penambahan' : 'stok sekarang' } { quantityChange < 1 ? currentQuantity + quantityChange : quantityChange } { materials [ selectedMaterialIndex ] ? . unit }
< / b u t t o n >
< / d i v >
< div onClick = { ( ) => setIsViewingHistory ( ! isViewingHistory ) } style = { styles . historyTab } >
< h3 > { isViewingHistory ? '˅' : '˃ ' } Riwayat stok < / h 3 >
< div style = { styles . historyContainer } >
{ selectedMaterialIndex != - 1 && isViewingHistory && ! loading && (
< div style = { styles . mutationContainer } >
{ sortedMutations . length > 0 ? (
sortedMutations . map ( ( mutation ) => (
< div key = { mutation . id } style = { styles . mutationCard } >
< h4 style = { styles . mutationTitle } >
{ formatDate ( mutation . createdAt ) }
< / h 4 >
< p > Details : { mutation . reason } < / p >
< p > stok { mutation . newStock } < / p >
< / d i v >
) )
) : (
< p > No mutations available . < / p >
) }
< / d i v >
) }
< / d i v >
< / d i v >
< / > :
< >
< div
style = { { display : "flex" , alignItems : "center" , margin : "10px" , marginTop : '17px' , marginBottom : '34px' } }
>
< div style = { { marginRight : "5px" , fontSize : "1.2em" } } > ⓘ < / d i v >
< h6 style = { { margin : 0 , textAlign : "left" } } >
Fitur ini mempermudah mengelola biaya dan memantau pengeluaran bahan .
< / h 6 >
< / d i v >
< div style = { styles . switchContainer } >
< h3 > Buat bahan baru < / h 3 >
< / d i v >
< div style = { styles . resultMessage } >
< input
style = { {
width : "100%" ,
height : '31px' ,
border : "1px solid #ccc"
} }
value = { newMaterialName }
onChange = { ( event ) => setNewMaterialName ( event . target . value ) }
placeholder = "Masukkan nama barang"
/ >
< / d i v >
< select
id = "materialUnit"
value = { newMaterialUnit }
onChange = { ( e ) => setNewMaterialUnit ( e . target . value ) }
style = { styles . unit }
>
< option value = "gram" > Satuan : gram < / o p t i o n >
< option value = "ons" > Satuan : ons < / o p t i o n >
< option value = "kilogram" > Satuan : kilogram < / o p t i o n >
< option value = "kuintal" > Satuan : kuintal < / o p t i o n >
< option value = "liter" > Satuan : liter < / o p t i o n >
< option value = "piece" > Satuan : piece < / o p t i o n >
< option value = "meter" > Satuan : meter < / o p t i o n >
< option value = "pack" > Satuan : pack < / o p t i o n >
< option value = "sachet" > Satuan : sachet < / o p t i o n >
< option value = "box" > Satuan : box < / o p t i o n >
< / s e l e c t >
< div style = { styles . buttonContainer } >
< button style = { styles . saveButton } >
Buat bahan baku
< / b u t t o n >
< / d i v >
< / >
}
< / >
}
< / d i v >
) ;
} ;
@@ -296,6 +379,7 @@ const SetPaymentQr = ({ cafeId }) => {
const styles = {
container : {
width : '100%' ,
minHeight : '50vh' ,
backgroundColor : "white" ,
padding : "20px" ,
borderRadius : "8px" ,
@@ -320,7 +404,7 @@ const styles = {
fontWeight : 600 ,
textAlign : "left" ,
} ,
uploadButton : {
changeButtonEnabled : {
paddingRight : '10px' ,
backgroundColor : 'green' ,
borderRadius : '30px' ,
@@ -331,6 +415,17 @@ const styles = {
paddingLeft : '10px' ,
paddingHeight : '10px' ,
} ,
changeButtonDisabled : {
paddingRight : '10px' ,
backgroundColor : '#a1a1a1' ,
borderRadius : '30px' ,
color : 'white' ,
fontWeight : 700 ,
height : '36px' ,
lineHeight : '36px' ,
paddingLeft : '10px' ,
paddingHeight : '10px' ,
} ,
resultMessage : {
marginTop : "-13px" ,
textAlign : "left" ,
@@ -341,15 +436,26 @@ const styles = {
display : 'flex' ,
justifyContent : 'space-evenly' ,
alignItems : 'center' ,
marginTop : '20 px' ,
marginTop : "20 px" ,
marginTop : '18 px' ,
marginBottom : "6 px" ,
textAlign : "left" ,
} ,
buttonContainer : {
marginTop : "20 px" ,
marginTop : "11 px" ,
textAlign : "left" ,
} ,
stockButton : {
padding : "10px 20px" ,
fontSize : "3.5vw" ,
backgroundColor : "#28a745" ,
color : "#fff" ,
border : "none" ,
borderRadius : "30px" ,
cursor : "pointer" ,
transition : "background-color 0.3s" ,
} ,
saveButton : {
width : '100%' ,
padding : "10px 20px" ,
fontSize : "3.5vw" ,
backgroundColor : "#28a745" ,
@@ -363,15 +469,24 @@ const styles = {
marginTop : "20px" ,
textAlign : "left" ,
} ,
historyContainer : {
marginTop : "20px" ,
historyTab : {
textAlign : "left" ,
} ,
historyContainer : {
textAlign : "left" ,
maxHeight : '200px' ,
overflowY : 'auto'
} ,
description : {
margin : "10px 0" ,
fontSize : "14px" ,
color : "#666" ,
} ,
unit : {
marginTop : '11px' ,
width : '100%' ,
height : '31px' ,
} ,
} ;
export default SetPaymentQr ;