App.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import React, { useState, useEffect } from 'react';
  2. import axios from 'axios';
  3. const API_URL = process.env.REACT_APP_API_URL || 'http://localhost:4000';
  4. function App() {
  5. const [users, setUsers] = useState([]);
  6. const [stats, setStats] = useState({ totalUsers: 0, activeUsers: 0, serverStatus: 'Unknown' });
  7. const [loading, setLoading] = useState(true);
  8. const [error, setError] = useState(null);
  9. useEffect(() => {
  10. fetchData();
  11. }, []);
  12. const fetchData = async () => {
  13. try {
  14. setLoading(true);
  15. setError(null);
  16. // Fetch users and stats in parallel
  17. const [usersResponse, statsResponse] = await Promise.all([
  18. axios.get(`${API_URL}/api/users`),
  19. axios.get(`${API_URL}/api/stats`)
  20. ]);
  21. setUsers(usersResponse.data);
  22. setStats(statsResponse.data);
  23. } catch (err) {
  24. console.error('Error fetching data:', err);
  25. setError(`Failed to fetch data: ${err.message}`);
  26. } finally {
  27. setLoading(false);
  28. }
  29. };
  30. const addSampleUser = async () => {
  31. try {
  32. const sampleUsers = [
  33. { name: 'Alice Johnson', email: 'alice@example.com', role: 'Developer' },
  34. { name: 'Bob Smith', email: 'bob@example.com', role: 'Designer' },
  35. { name: 'Charlie Brown', email: 'charlie@example.com', role: 'Manager' },
  36. { name: 'Diana Prince', email: 'diana@example.com', role: 'Tester' }
  37. ];
  38. const randomUser = sampleUsers[Math.floor(Math.random() * sampleUsers.length)];
  39. await axios.post(`${API_URL}/api/users`, randomUser);
  40. // Refresh data
  41. fetchData();
  42. } catch (err) {
  43. console.error('Error adding user:', err);
  44. setError(`Failed to add user: ${err.message}`);
  45. }
  46. };
  47. if (loading) {
  48. return (
  49. <div className="container">
  50. <div className="card">
  51. <div className="loading">Loading BYOP Sample Application...</div>
  52. </div>
  53. </div>
  54. );
  55. }
  56. return (
  57. <div className="container">
  58. <div className="card">
  59. <div className="header">
  60. <h1>🚀 BYOP Sample App</h1>
  61. <p>Multi-Component Application Testing Platform</p>
  62. </div>
  63. {error && (
  64. <div className="error">
  65. {error}
  66. </div>
  67. )}
  68. <div className="system-info">
  69. <h4>🔧 System Information</h4>
  70. <p><strong>Frontend:</strong> React 18 (Port 3000)</p>
  71. <p><strong>Backend API:</strong> Node.js + Express (Port 5000)</p>
  72. <p><strong>Database:</strong> PostgreSQL (Port 5432)</p>
  73. <p><strong>Environment:</strong> {process.env.NODE_ENV || 'development'}</p>
  74. <p><strong>API URL:</strong> {API_URL}</p>
  75. </div>
  76. <div className="stats-grid">
  77. <div className="stat-card">
  78. <h3>{stats.totalUsers}</h3>
  79. <p>Total Users</p>
  80. </div>
  81. <div className="stat-card">
  82. <h3>{stats.activeUsers}</h3>
  83. <p>Active Users</p>
  84. </div>
  85. <div className="stat-card">
  86. <h3>{stats.serverStatus}</h3>
  87. <p>Server Status</p>
  88. </div>
  89. </div>
  90. <div className="users-section">
  91. <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '20px' }}>
  92. <h2>👥 Users ({users.length})</h2>
  93. <button className="btn" onClick={addSampleUser}>
  94. Add Sample User
  95. </button>
  96. </div>
  97. {users.length === 0 ? (
  98. <div style={{ textAlign: 'center', padding: '40px', color: '#666' }}>
  99. <p>No users found. Click "Add Sample User" to get started!</p>
  100. </div>
  101. ) : (
  102. <div className="users-grid">
  103. {users.map((user) => (
  104. <div key={user.id} className="user-card">
  105. <h4>{user.name}</h4>
  106. <p><strong>Email:</strong> {user.email}</p>
  107. <p><strong>Role:</strong> {user.role}</p>
  108. <p><strong>Created:</strong> {new Date(user.created_at).toLocaleDateString()}</p>
  109. </div>
  110. ))}
  111. </div>
  112. )}
  113. </div>
  114. <div style={{ textAlign: 'center', marginTop: '40px', padding: '20px', background: '#f8f9fa', borderRadius: '8px' }}>
  115. <h3>🧪 BYOP Engine Test Status</h3>
  116. <p>This application demonstrates:</p>
  117. <ul style={{ textAlign: 'left', maxWidth: '600px', margin: '0 auto' }}>
  118. <li>✅ Multi-component architecture (Frontend + Backend + Database)</li>
  119. <li>✅ Docker containerization with individual Dockerfiles</li>
  120. <li>✅ Docker Compose orchestration</li>
  121. <li>✅ API communication between services</li>
  122. <li>✅ Database persistence and operations</li>
  123. <li>✅ Production-ready builds with Nginx</li>
  124. </ul>
  125. <button className="btn" onClick={fetchData} style={{ marginTop: '20px' }}>
  126. 🔄 Refresh Data
  127. </button>
  128. </div>
  129. </div>
  130. </div>
  131. );
  132. }
  133. export default App;