2024-11-25 17:51:46 +07:00

347 lines
11 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { CopyToClipboard } from 'react-copy-to-clipboard';
const Template = () => {
const BASE_URL = process.env.REACT_APP_BASE_URL;
const API_KEY = process.env.REACT_APP_API_KEY;
const [ownership, setOwnership] = useState([]);
const [buttonStates, setButtonStates] = useState([]);
const [copiedIndex, setCopiedIndex] = useState(null);
const [searchTerm, setSearchTerm] = useState(''); // state for search term
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState(''); // state for debounced search term
const [errorMessage, setErrorMessage] = useState(null); // state for error message
// Debounce search term input
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedSearchTerm(searchTerm);
}, 500); // Delay of 500ms before search term is sent
return () => clearTimeout(timer); // Clear timeout when searchTerm changes
}, [searchTerm]);
// Fetch applications based on the search term
useEffect(() => {
let isMounted = true;
const fetchApplications = async () => {
if (debouncedSearchTerm) {
// Fetch by search term
try {
const response = await fetch(`${BASE_URL}/application/get-by-name/${debouncedSearchTerm}`, {
method: 'GET',
headers: {
'accept': 'application/json',
'x-api-key': API_KEY,
},
});
const result = await response.json();
if (response.ok) {
if (result.details && result.details.data) {
if (isMounted) {
setOwnership([result.details.data]);
setButtonStates([{ isHovered: false, isActive: false }]);
setErrorMessage(null); // Reset error if data found
}
} else {
if (isMounted) {
setOwnership([]);
setErrorMessage('Data is not found.');
}
}
} else {
if (isMounted) {
setOwnership([]);
setErrorMessage('Data is not found.');
}
}
} catch (error) {
console.error('Error fetching applications:', error);
if (isMounted) {
setOwnership([]);
setErrorMessage('Data is not found.');
}
}
} else {
// Fetch all applications when there's no search term
const fetchAllApplications = async () => {
try {
const response = await fetch(`${BASE_URL}/application/list`, {
method: 'GET',
headers: {
'x-api-key': API_KEY,
},
});
const result = await response.json();
if (response.ok && result.status_code === 200) {
if (isMounted) {
setOwnership(result.details.data);
setButtonStates(result.details.data.map(() => ({ isHovered: false, isActive: false })));
setErrorMessage(null); // Reset error if data found
}
} else {
if (isMounted) {
setOwnership([]);
setErrorMessage('Error fetching data. Please try again.');
}
}
} catch (error) {
console.error('Error fetching all applications:', error);
if (isMounted) {
setOwnership([]);
setErrorMessage('Error fetching data. Please try again.');
}
}
};
fetchAllApplications();
}
};
fetchApplications();
return () => {
isMounted = false; // Set the flag to false on cleanup
};
}, [debouncedSearchTerm]); // Trigger the effect when `debouncedSearchTerm` changes
const handleMouseEnter = (index) => {
setButtonStates((prevStates) => {
const newStates = [...prevStates];
newStates[index].isHovered = true;
return newStates;
});
};
const handleMouseLeave = (index) => {
setButtonStates((prevStates) => {
const newStates = [...prevStates];
newStates[index].isHovered = false;
return newStates;
});
};
const handleChange = (event) => {
setSearchTerm(event.target.value);
};
return (
<div style={styles.container}>
{/* Welcome Message */}
<div className="row-card border-left border-primary shadow mb-4" style={styles.welcomeCard}>
<div className="d-flex flex-column justify-content-start align-items-start p-4">
<div>
<h4 className="mb-3 text-start">
<i className="fas fa-message fa-bold me-3"></i>Create WhatsApp Business Templates
</h4>
<p className="mb-0 text-start">
Design pre-approved message templates tailored for various business needs, such as customer support, appointment reminders, order updates, and more. Streamline communication and ensure consistency with ready-to-use templates.
</p>
</div>
<div className="d-flex flex-row mt-3">
<Link to="/" style={{ textDecoration: 'none' }}>
<button className="btn d-flex justify-content-center align-items-center me-2" style={styles.createButton}>
<i className="fas fa-plus text-white me-2"></i>
<p className="text-white mb-0">Create Template</p>
</button>
</Link>
</div>
</div>
</div>
<div style={styles.wrapperCard}>
<div className="card mt-3">
<div className="row">
{/* Filtering Options */}
<div className="col-md-2">
<select className="form-control">
<option value="">Pilih WABA IDI</option>
<option value="waba1">WABA 1</option>
<option value="waba2">WABA 2</option>
<option value="waba3">WABA 3</option>
</select>
</div>
<div className="col-md-2">
<select className="form-control">
<option value="">Pilih Kategori</option>
<option value="kategori1">Kategori 1</option>
<option value="kategori2">Kategori 2</option>
<option value="kategori3">Kategori 3</option>
</select>
</div>
<div className="col-md-2">
<select className="form-control">
<option value="">Pilih Status</option>
<option value="aktif">Aktif</option>
<option value="non-aktif">Non-Aktif</option>
<option value="pending">Pending</option>
</select>
</div>
<div className="col-md-2 d-flex align-items-end" style={{ gap: '10px' }}>
<button className="btn btn-primary w-100">Apply</button>
<button className="btn btn-secondary w-100">Cancel</button>
</div>
</div>
</div>
{/* Search Bar */}
<div style={styles.searchInputWrapper}>
<input
type="text"
placeholder="Type your keywords here"
style={styles.searchInput}
value={searchTerm}
onChange={handleChange}
/>
<button style={styles.searchButton}>
<i className="fas fa-search" style={styles.searchIcon}></i>
</button>
</div>
{/* Application Cards */}
<div style={styles.cardContainer}>
{/* Show message if no data or search result */}
{ownership.length === 0 && !errorMessage && <p style={styles.noDataMessage}>Data is not found.</p>}
{ownership.map((item, index) => (
<div key={item.id} style={styles.card}>
<div style={styles.cardHeader}>
<span style={styles.cardTitle}>{item.name}</span>
</div>
<div style={styles.cardContent}>
<div style={styles.applicationIdWrapper}>
<p><strong>WABA Ownership:</strong></p>
<p>{item.name}</p>
</div>
{/* Copy to Clipboard Button */}
<CopyToClipboard
key={index}
text={item.name}
onCopy={() => {
setCopiedIndex(index);
setTimeout(() => setCopiedIndex(null), 2000); // Hide "Copied" status after 2 seconds
}}
>
<button
style={{
backgroundColor: copiedIndex === index ? '#4BA5E7' : '#0542cc',
padding: '10px 20px',
color: 'white',
border: 'none',
cursor: 'pointer',
}}
onMouseEnter={() => handleMouseEnter(index)}
onMouseLeave={() => handleMouseLeave(index)}
>
{copiedIndex === index ? (
<i className="fas fa-check"></i> // Show check icon if copied
) : (
<i className="fas fa-copy"></i> // Show copy icon
)}
{copiedIndex === index ? 'Copied' : 'Copy'}
</button>
</CopyToClipboard>
</div>
</div>
))}
</div>
{/* Show error message */}
{errorMessage && <p style={styles.errorMessage}>{errorMessage}</p>}
</div>
</div>
);
};
const styles = {
container: {
margin: '20px auto',
maxWidth: '1200px',
},
welcomeCard: {
backgroundColor: '#F1F3F6',
borderColor: '#1e2b34',
borderRadius: '5px',
marginBottom: '20px',
},
createButton: {
backgroundColor: '#1d3f68',
color: '#fff',
borderRadius: '5px',
padding: '12px 20px',
width: '150px',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
},
wrapperCard: {
padding: '20px',
},
searchInputWrapper: {
display: 'flex',
alignItems: 'center',
marginTop: '20px',
marginBottom: '20px',
},
searchInput: {
padding: '10px',
border: '1px solid #ccc',
borderRadius: '5px',
width: '300px',
marginRight: '10px',
},
searchButton: {
backgroundColor: '#1d3f68',
border: 'none',
color: 'white',
padding: '10px 15px',
cursor: 'pointer',
},
searchIcon: {
fontSize: '16px',
},
cardContainer: {
display: 'grid',
gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))',
gap: '20px',
},
card: {
backgroundColor: '#fff',
border: '1px solid #ddd',
borderRadius: '10px',
padding: '20px',
boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',
},
cardHeader: {
marginBottom: '10px',
},
cardTitle: {
fontSize: '18px',
fontWeight: 'bold',
},
cardContent: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
},
applicationIdWrapper: {
display: 'flex',
flexDirection: 'column',
},
noDataMessage: {
color: 'gray',
},
errorMessage: {
color: 'red',
}
};
export default Template;