source: frontend/web3-eDnevnik_Frontend/src/pages/RoditelPages/Roditel_PaymentAnnoucements/Roditel_PaymentAnnoucements.jsx

Last change on this file was 81cdf2d, checked in by Nikola Janev <nikolajanev57@…>, 9 days ago

initial commit

  • Property mode set to 100644
File size: 7.3 KB
Line 
1import NavbarRoditel from "../../../components/NavbarRoditel/NavbarRoditel";
2import { useState, useEffect } from "react";
3import { ethers } from "ethers";
4import { data } from "react-router-dom";
5import axios from "axios";
6import { useAuth } from "../../../contexts/AuthContext";
7
8const Roditel_PaymentAnnoucements = () => {
9 const { walletAddress } = useAuth(); //go zimame wallet od AuthContext
10 const [soopstenija, setSoopstenija] = useState([]);
11 const [paymentLoading, setPaymentLoading] = useState(null);
12 const [roditelId, setRoditelId] = useState(null);
13 const [paymentStatus, setPaymentStatus] = useState(null);
14 const [txPending, setTxPending] = useState(false);
15 const [plateniSoopstenija, setPlateniSoopstenija] = useState([]);
16
17 useEffect(() => {
18 const fetchRoditelAndPlateniSoopstenija = async () => {
19 try {
20 const response = await fetch("http://localhost:8080/api/auth/me", {
21 credentials: "include",
22 });
23 const data = await response.json();
24 setRoditelId(data.id);
25 const id = data.id;
26 const plateniResponse = await axios.get(
27 `http://localhost:8080/api/payments/parent/${id}`,
28 { withCredentials: true }
29 );
30 setPlateniSoopstenija(plateniResponse.data);
31 } catch (err) {
32 console.error("Error fetching roditel ID:", err);
33 }
34 };
35
36 fetchRoditelAndPlateniSoopstenija();
37 }, []);
38
39 const fetchSoopstenija = async () => {
40 try {
41 const response = await axios.get(
42 "http://localhost:8080/api/paymentsSoopstenija/approved",
43 { withCredentials: true }
44 );
45 setSoopstenija(response.data);
46 } catch (error) {
47 console.error("Error fetching soopstenija:", error);
48 }
49 };
50 useEffect(() => {
51 fetchSoopstenija();
52 }, []);
53
54 const handlePayment = async (soopstenieId, iznosETH) => {
55 if (!walletAddress) {
56 alert("Ве молиме прво поврзете го вашиот MetaMask wallet во Settings!");
57 return;
58 }
59
60 if (!roditelId) {
61 alert("Грешка: Не може да се идентификува родителот!");
62 return;
63 }
64
65 setPaymentLoading(soopstenieId);
66 setTxPending(true);
67
68 try {
69 // 1. Креирај плаќање
70 const createResponse = await axios.post(
71 "http://localhost:8080/api/payments/create",
72 {
73 soopstenieId: soopstenieId,
74 roditelId: roditelId,
75 },
76 { withCredentials: true }
77 );
78
79 const payment = createResponse.data;
80
81 const txHash = await sendTransaction(iznosETH);
82
83 await axios.post(
84 `http://localhost:8080/api/payments/${payment.id}/submit-tx`,
85 {
86 txHash: txHash,
87 },
88 { withCredentials: true }
89 );
90
91 alert(
92 `Успешно плаќање!\nTx hash: ${txHash.substring(
93 0,
94 10
95 )}...\nПроверете на Sepolia Etherscan`
96 );
97
98 fetchSoopstenija();
99 } catch (error) {
100 console.error("Грешка:", error);
101 if (error.response?.data) {
102 alert(error.response.data);
103 } else if (error.message.includes("insufficient funds")) {
104 alert(
105 "Немате доволно SepoliaETH! Добијте од faucet: https://sepoliafaucet.com/"
106 );
107 } else {
108 alert("Грешка при плаќање: " + error.message);
109 }
110 } finally {
111 setTxPending(false);
112 setPaymentLoading(null);
113 }
114 };
115
116 const sendTransaction = async (iznosETH) => {
117 if (!window.ethereum) {
118 throw new Error("MetaMask не е инсталиран");
119 }
120
121 const provider = new ethers.BrowserProvider(window.ethereum);
122 const signer = await provider.getSigner();
123
124 const toAddress = "0x1ab6B15AfE81B57fF4a692fbb8C141A1858941e0";
125
126 const amountInWei = ethers.parseEther(Number(iznosETH).toFixed(18));
127 const tx = await signer.sendTransaction({
128 to: toAddress,
129 value: amountInWei,
130 });
131
132 console.log("Transaction sent:", tx.hash);
133
134 setPaymentStatus("Испратена трансакција, ве молиме почекајте");
135
136 await tx.wait(3);
137
138 return tx.hash;
139 };
140
141 const isPlateno = (soopstenieId) => {
142 return plateniSoopstenija.some((p) => p.soopstenieId === soopstenieId);
143 };
144 return (
145 <>
146 <NavbarRoditel />
147 <div className="payment-announcements-container ">
148 <h2 className="text-center">Соопштенија за плаќање</h2>
149
150 {!walletAddress && (
151 <div className="alert alert-warning w-50 m-5 p-2 " role="alert">
152 Немате поврзано <b>Metamusk Wallet!</b> Ве молиме поврзете го вашиот
153 <b>MetaMask wallet</b> во опции!
154 </div>
155 )}
156
157 {soopstenija.length === 0 ? (
158 <p>Нема активни соопштенија за плаќање.</p>
159 ) : (
160 <div className="soopstenija-list">
161 {soopstenija.map((soopstenie) => (
162 <div key={soopstenie.id} className="card w-50 m-5">
163 <div className="card-header">
164 <h3>Наслов {soopstenie.naslov}</h3>
165 </div>
166 <div className="card-body">
167 <p className="card-text">{soopstenie.sodrzina}</p>
168 <p>
169 <b>Износ: </b>
170 {Number(soopstenie.iznos).toFixed(18)} ETH
171 </p>
172 <p>soopstenie id: {soopstenie.id}</p>
173 <p>
174 Рок:{" "}
175 {new Date(soopstenie.rokZaPlakjanje).toLocaleDateString()}
176 </p>
177 <p>{soopstenie.plateno}</p>
178 {paymentLoading === soopstenie.id || !walletAddress ? (
179 <p>Немате поврзано wallet! за да платете!</p>
180 ) : isPlateno(soopstenie.id) ? (
181 <span className="text-success">
182 Оваа соопштение е веќе платено!
183 </span>
184 ) : (
185 <button
186 onClick={() =>
187 handlePayment(soopstenie.id, soopstenie.iznos)
188 }
189 >
190 Плати
191 </button>
192 )}
193 </div>
194 </div>
195 ))}
196 </div>
197 )}
198 </div>
199 {txPending && (
200 <div
201 style={{
202 position: "fixed",
203 inset: 0,
204 background: "rgba(0,0,0,0.5)",
205 display: "flex",
206 alignItems: "center",
207 justifyContent: "center",
208 zIndex: 1000,
209 }}
210 >
211 <div
212 style={{
213 background: "#fff",
214 borderRadius: 16,
215 padding: "2rem 2.5rem",
216 textAlign: "center",
217 maxWidth: 320,
218 }}
219 >
220 <div style={{ fontSize: 32, marginBottom: 12 }}></div>
221 <h3 style={{ margin: "0 0 8px" }}>Transaction in progress</h3>
222 <p style={{ margin: 0, color: "#666", fontSize: 14 }}>
223 Please don't close this window
224 </p>
225 </div>
226 </div>
227 )}
228 </>
229 );
230};
231
232export default Roditel_PaymentAnnoucements;
Note: See TracBrowser for help on using the repository browser.