diff --git a/src/App.js b/src/App.js
index 0a37693..b7f8f8d 100644
--- a/src/App.js
+++ b/src/App.js
@@ -413,27 +413,27 @@ function App() {
setModalContent(content)
};
- // Function to close the modal
const closeModal = (closeTheseContent = []) => {
if (
Array.isArray(closeTheseContent) &&
- (closeTheseContent.length === 0 ||
- closeTheseContent.includes(modalContent))
+ (closeTheseContent.length === 0 || closeTheseContent.includes(modalContent))
) {
setIsModalOpen(false);
setModalContent(null);
document.body.style.overflow = "auto";
-
+
const queryParams = new URLSearchParams(location.search);
-
- // Remove the 'modal' parameter
- queryParams.delete("modal");
- queryParams.delete("transactionId");
-
- // Update the URL without the 'modal' parameter
+
+ // Clear all query parameters
+ queryParams.keys() && [...queryParams.keys()].forEach(key => {
+ queryParams.delete(key);
+ });
+
+ // Update the URL without any query parameters
navigate({ search: queryParams.toString() }, { replace: true });
}
};
+
// useEffect(() => {
// const askNotificationPermission = async () => {
diff --git a/src/components/Coupon.css b/src/components/Coupon.css
new file mode 100644
index 0000000..c4514d8
--- /dev/null
+++ b/src/components/Coupon.css
@@ -0,0 +1,56 @@
+/* Coupon container */
+.coupon {
+ display: flex;
+ border: 2px solid #ccc;
+ height: 50%;
+ background-color: #f8f8f8;
+ border-radius: 8px;
+ font-family: Arial, sans-serif;
+ align-items: center;
+ }
+
+ /* Left side (with the rotated code and dotted line) */
+ .coupon-left {
+ width: 80px;
+ position: relative;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border-right: 2px dotted #ccc;
+ height: 100%;
+ }
+
+ .coupon-code {
+ writing-mode: vertical-rl;
+ font-size: 18px;
+ font-weight: bold;
+ color: #333;
+ margin: 0;
+ }
+
+ .dotted-line {
+ position: absolute;
+ left: 0;
+ bottom: 10px;
+ width: 60px;
+ border-bottom: 2px dotted #ccc;
+ }
+
+ /* Right side (coupon details) */
+ .coupon-right {
+ padding: 10px;
+ flex-grow: 1;
+ }
+ .coupon-value {
+ font-size: clamp(18px, 3vw, 24px); /* Minimum 18px, 6vw (responsive), Maximum 24px */
+ font-weight: bold;
+ color: #2c3e50;
+ text-align: left;
+ }
+
+ .coupon-period,
+ .coupon-expiration {
+ font-size: 14px;
+ color: #7f8c8d;
+ }
+
\ No newline at end of file
diff --git a/src/components/Coupon.js b/src/components/Coupon.js
new file mode 100644
index 0000000..0619063
--- /dev/null
+++ b/src/components/Coupon.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import './Coupon.css'; // Import a CSS file for styling
+
+const Coupon = ({ code, value, period, type, expiration }) => {
+ // Format the value based on type
+ const formattedValue = type === 'fixed' ? `Rp ${value}` : value != 0 ? `${value}%` : 'kupon berlangganan';
+
+ return (
+
+
+
{code == null ? '404' : code}
+
+
+
+
{code == null ? 'Kupon tidak ditemukan' : formattedValue}
+ {type &&
{type}} {/* Display type if provided */}
+
+ {code == null ? '-' : value == 0 ? `Masa berlangganan ${period} minggu` : `Masa kupon ${period} minggu`} {/* Fixed string concatenation */}
+
+
+ {expiration == null ? (code == null ? '-' : 'Tanpa kadaluarsa') : `Berlaku sampai: ${expiration}`}
+
+
+
+ );
+};
+
+export default Coupon;
diff --git a/src/components/Modal.js b/src/components/Modal.js
index a979504..bd0161e 100644
--- a/src/components/Modal.js
+++ b/src/components/Modal.js
@@ -30,6 +30,7 @@ import { getImageUrl } from "../helpers/itemHelper.js";
import CreateCoupon from "../pages/CreateCoupon";
import CheckCoupon from "../pages/CheckCoupon";
+import CreateUserWithCoupon from "../pages/CreateUserWithCoupon";
const Modal = ({ user, shop, isOpen, onClose, modalContent, setModal, handleMoveToTransaction,welcomePageConfig }) => {
@@ -60,7 +61,7 @@ const Modal = ({ user, shop, isOpen, onClose, modalContent, setModal, handleMove
{modalContent === "edit_account" &&
}
- {modalContent === "join" &&
}
+ {modalContent === "join" &&
}
{modalContent === "reset-password" &&
}
{modalContent === "req_notification" &&
}
{modalContent === "blocked_notification" &&
}
@@ -103,6 +104,7 @@ const Modal = ({ user, shop, isOpen, onClose, modalContent, setModal, handleMove
{modalContent === "create_coupon" &&
}
{modalContent === "check_coupon" &&
}
+ {modalContent === "create_user" &&
}
);
diff --git a/src/pages/CreateUserWithCoupon.js b/src/pages/CreateUserWithCoupon.js
index e69de29..16e7ab5 100644
--- a/src/pages/CreateUserWithCoupon.js
+++ b/src/pages/CreateUserWithCoupon.js
@@ -0,0 +1,123 @@
+import React, { useState } from 'react';
+import styles from './Join.module.css'; // Import the module.css file
+import API_BASE_URL from '../config.js';
+
+function getAuthToken() {
+ return localStorage.getItem('auth');
+}
+
+const LinktreePage = ({ setModal }) => {
+ const [isUsingCoupon, setIsUsingCoupon] = useState(false);
+ const [couponCode, setCouponCode] = useState('');
+ const [couponStatus, setCouponStatus] = useState('');
+ const [couponDetails, setCouponDetails] = useState(null);
+ const [username, setUsername] = useState('');
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [retypePassword, setRetypePassword] = useState('');
+
+ const handleCheckCoupon = async (e) => {
+ e.preventDefault();
+ try {
+ const response = await fetch(`${API_BASE_URL}/coupon/check/${couponCode}`, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${getAuthToken()}`,
+ },
+ });
+
+ if (response.ok) {
+ const data = await response.json();
+ setCouponStatus('Coupon is valid');
+ setCouponDetails(data.coupon);
+ } else {
+ setCouponStatus('Coupon not found or expired');
+ setCouponDetails(null);
+ }
+ } catch (error) {
+ setCouponStatus('Error checking coupon.');
+ setCouponDetails(null);
+ }
+ };
+
+ const handleCreateUserWithCoupon = async (e) => {
+ e.preventDefault();
+
+ if (password !== retypePassword) {
+ setCouponStatus('Passwords do not match');
+ return;
+ }
+
+ try {
+ const response = await fetch(`${API_BASE_URL}/user/create-with-coupon`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${getAuthToken()}`,
+ },
+ body: JSON.stringify({
+ username,
+ email,
+ password,
+ couponCode,
+ }),
+ });
+
+ if (response.ok) {
+ const data = await response.json();
+ setCouponStatus('User created successfully with coupon');
+ setCouponDetails(null);
+ console.log(data);
+ } else {
+ const errorData = await response.json();
+ setCouponStatus(errorData.message || 'Error creating user');
+ }
+ } catch (error) {
+ setCouponStatus('Error creating user.');
+ }
+ };
+
+ return (
+
+ );
+};
+
+export default LinktreePage;
diff --git a/src/pages/Dashboard.js b/src/pages/Dashboard.js
index 75cae57..5d32462 100644
--- a/src/pages/Dashboard.js
+++ b/src/pages/Dashboard.js
@@ -946,7 +946,7 @@ const sortedMaterials = allMaterials.sort((a, b) => new Date(a.date) - new Date(
onError={(e) => e.target.src = '/fallback-image.png'}
/>
- ©2025 KEDIRITECHNOPARK
+ ©2025 KEDIRITECHNOPARK.COM
diff --git a/src/pages/Join.js b/src/pages/Join.js
index c4e6647..52de2e8 100644
--- a/src/pages/Join.js
+++ b/src/pages/Join.js
@@ -1,63 +1,162 @@
-import React from 'react';
+import React, { useState } from 'react';
import styles from './Join.module.css'; // Import the module.css file
+import API_BASE_URL from '../config.js';
+
+import Coupon from '../components/Coupon';
+
+function getAuthToken() {
+ return localStorage.getItem('auth');
+}
+
+const LinktreePage = ({ data, setModal }) => {
+ const [isUsingCoupon, setIsUsingCoupon] = useState(false);
+ const [couponCode, setCouponCode] = useState('');
+ const [couponStatus, setCouponStatus] = useState(0);
+ const [couponDetails, setCouponDetails] = useState(null);
+
+ const handleCheckCoupon = async (e) => {
+ e.preventDefault();
+ try {
+ const response = await fetch(`${API_BASE_URL}/coupon/check/${couponCode}`, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${getAuthToken()}`,
+ },
+ });
+
+ if (response.ok) {
+ const data = await response.json();
+ setCouponStatus(200);
+ setCouponDetails(data.coupon);
+ } else {
+ setCouponStatus(404);
+ setCouponDetails(null);
+ }
+ } catch (error) {
+ setCouponStatus(404);
+ setCouponDetails(null);
+ }
+ };
-const LinktreePage = ({ data }) => {
return (
+ {!isUsingCoupon ? (
+
+ {/* Main Heading */}
+
Nikmati Kemudahan Mengelola Kafe
-
- {/* Main Heading */}
-
- Nikmati Kemudahan Mengelola Kafe
-
-
- {/* Sub Heading */}
-
- Daftarkan kedaimu sekarang dan mulai gunakan semua fitur unggulan kami.
-
-
- {/* Form Section */}
-
-
- {/* Footer Links */}
-
-
-
- Pelajari lebih lanjut
-
-
- Gunakan kupon
-
+ {/* Sub Heading */}
+
+ Daftarkan kedaimu sekarang dan mulai gunakan semua fitur unggulan kami.
-
-

+
+
+
+
+
+ {/* Footer Links */}
+
+
+
+

+
-
+ ) : (
+
+ {/* Main Heading */}
+
Daftar Menggunakan Kupon
+
+ {/* Sub Heading */}
+
+ Kupon tidak hanya dapat digunakan untuk pembuatan akun penyewa, tetapi juga dapat digunakan untuk memperpanjang masa berlangganan.
+
+
+ {/* Coupon Check Section */}
+ {couponStatus == 0 ?
+
+ :
+ <>
+
+
+
+
+ >
+ }
+ {/* Footer Links */}
+
+
+
+

+
+
+
+ )}
);
};