Changeset 79fff4f


Ignore:
Timestamp:
02/22/26 22:32:07 (7 months ago)
Author:
Klimentina Efremova <klimentina08642@…>
Branches:
finki-main, main
Children:
6fea37e, 81bc7da
Parents:
4dff800
Message:

Improved employee logging in and changing password

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • interfejs/admin.html

    r4dff800 r79fff4f  
    1818      <li><a href="products.html">Products</a></li>
    1919      <li><a href="#" id="dashboard-link" class="active">Admin</a></li>
     20      <li><a href="change-password.html" class="change-password-btn">🔑 Change Password</a></li>
     21      <li><a href="#" id="logout-link">Logout</a></li>
    2022    </ul>
    2123  </nav>
    … …  
    201203  document.addEventListener('DOMContentLoaded', async () => {
    202204    const user = await loadUserData();
     205
    203206    if (!user || user.userType !== 'admin') {
    204207      window.location.href = 'index.html';
    … …  
    207210
    208211    document.getElementById('admin-name').textContent = user.username || 'Administrator';
     212
     213    // Logout functionality
     214    document.getElementById('logout-link').addEventListener('click', async (e) => {
     215      e.preventDefault();
     216      await logout();
     217    });
    209218
    210219    // Tab switching
    … …  
    213222        document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
    214223        document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
     224
    215225        btn.classList.add('active');
    216226        document.getElementById(`${btn.dataset.tab}-tab`).classList.add('active');
    … …  
    271281
    272282      const tbody = document.getElementById('users-list');
     283
    273284      if (data.success && data.users.length > 0) {
    274285        tbody.innerHTML = data.users.map(user => `
    275                         <tr>
    276                             <td>${user.id || user.client_id || 'N/A'}</td>
    277                             <td>${user.firstName || user.first_name || user.username || 'N/A'} ${user.lastName || user.last_name || ''}</td>
    278                             <td>${user.email || 'N/A'}</td>
    279                             <td><span class="status-badge status-${user.user_type || user.userType || 'unknown'}">${user.user_type || user.userType || 'unknown'}</span></td>
    280                             <td>
    281                                 <button class="btn-small" onclick="viewUser('${user.id || user.client_id}')">View</button>
    282                             </td>
    283                         </tr>
    284                     `).join('');
     286                    <tr>
     287                        <td>${user.id || user.client_id || 'N/A'}</td>
     288                        <td>${user.firstName || user.first_name || user.username || 'N/A'} ${user.lastName || user.last_name || ''}</td>
     289                        <td>${user.email || 'N/A'}</td>
     290                        <td><span class="status-badge status-${user.user_type || user.userType || 'unknown'}">${user.user_type || user.userType || 'unknown'}</span></td>
     291                        <td>
     292                            <button class="btn-small" onclick="viewUser('${user.id || user.client_id}')">View</button>
     293                        </td>
     294                    </tr>
     295                `).join('');
    285296      } else {
    286297        tbody.innerHTML = '<tr><td colspan="5">No users found</td></tr>';
    … …  
    298309
    299310      const tbody = document.getElementById('stores-list');
     311
    300312      if (data.success && data.stores.length > 0) {
    301313        tbody.innerHTML = data.stores.map(store => `
    302                         <tr>
    303                             <td>${store.store_id}</td>
    304                             <td>${store.name}</td>
    305                             <td>${store.store_email}</td>
    306                             <td>${store.rating || '0.0'}</td>
    307                             <td>
    308                                 <button class="btn-small" onclick="viewStore('${store.store_id}')">View</button>
    309                             </td>
    310                         </tr>
    311                     `).join('');
     314                    <tr>
     315                        <td>${store.store_id}</td>
     316                        <td>${store.name}</td>
     317                        <td>${store.store_email}</td>
     318                        <td>${store.rating || '0.0'}</td>
     319                        <td>
     320                            <button class="btn-small" onclick="viewStore('${store.store_id}')">View</button>
     321                        </td>
     322                    </tr>
     323                `).join('');
    312324      } else {
    313325        tbody.innerHTML = '<tr><td colspan="5">No stores found</td></tr>';
    … …  
    325337
    326338      const tbody = document.getElementById('orders-list');
     339
    327340      if (data.success && data.orders.length > 0) {
    328341        tbody.innerHTML = data.orders.map(order => `
    329                         <tr>
    330                             <td>${order.order_num}</td>
    331                             <td>${order.first_name} ${order.last_name}</td>
    332                             <td>${order.store_name}</td>
    333                             <td>${new Date(order.order_date).toLocaleDateString()}</td>
    334                             <td><span class="status-badge status-${order.status}">${order.status}</span></td>
    335                             <td>$${parseFloat(order.total || 0).toFixed(2)}</td>
    336                         </tr>
    337                     `).join('');
     342                    <tr>
     343                        <td>${order.order_num}</td>
     344                        <td>${order.first_name} ${order.last_name}</td>
     345                        <td>${order.store_name}</td>
     346                        <td>${new Date(order.order_date).toLocaleDateString()}</td>
     347                        <td><span class="status-badge status-${order.status}">${order.status}</span></td>
     348                        <td>$${parseFloat(order.total || 0).toFixed(2)}</td>
     349                    </tr>
     350                `).join('');
    338351      } else {
    339352        tbody.innerHTML = '<tr><td colspan="6">No orders found</td></tr>';
    … …  
    362375    // Mock report generation
    363376    document.getElementById('report-results').innerHTML = `
    364                 <div class="dashboard-section">
    365                     <h4>Generated Report: ${type}</h4>
    366                     <p>Period: ${start} to ${end}</p>
    367                     <div class="loading">Generating report...</div>
    368                 </div>
    369             `;
     377            <div class="dashboard-section">
     378                <h4>Generated Report: ${type}</h4>
     379                <p>Period: ${start} to ${end}</p>
     380                <div class="loading">Generating report...</div>
     381            </div>
     382        `;
    370383
    371384    // Simulate report generation
    372385    setTimeout(() => {
    373386      document.getElementById('report-results').innerHTML = `
    374                     <div class="dashboard-section">
    375                         <h4>Report Results</h4>
    376                         <p><strong>Total Records:</strong> 42</p>
    377                         <p><strong>Summary:</strong> Sample report data for demonstration</p>
    378                         <button class="btn-small" onclick="downloadReport()">Download Report</button>
    379                     </div>
    380                 `;
     387                <div class="dashboard-section">
     388                    <h4>Report Results</h4>
     389                    <p><strong>Total Records:</strong> 42</p>
     390                    <p><strong>Summary:</strong> Sample report data for demonstration</p>
     391                    <button class="btn-small" onclick="downloadReport()">Download Report</button>
     392                </div>
     393            `;
    381394    }, 1500);
    382395  }
  • interfejs/change-password.html

    r4dff800 r79fff4f  
    1717            <li><a href="index.html">Home</a></li>
    1818            <li><a href="products.html">Products</a></li>
    19             <li><a href="login.html">Login</a></li>
     19            <li><a href="#" id="dashboard-link">Dashboard</a></li>
    2020        </ul>
    2121    </nav>
    … …  
    2323
    2424<main>
    25     <div class="form-container">
     25    <div class="auth-container">
    2626        <h2>Change Password</h2>
    27         <p class="form-subtitle" id="password-message">Please set a new password</p>
    28 
    29         <div id="error-message" class="error-message" style="display: none; color: red; margin-bottom: 1rem; padding: 10px; background-color: #ffeeee; border-radius: 5px;"></div>
    30         <div id="success-message" class="success-message" style="display: none; color: green; margin-bottom: 1rem; padding: 10px; background-color: #eeffee; border-radius: 5px;"></div>
     27        <div id="password-message" class="message"></div>
    3128
    3229        <form id="change-password-form" class="form">
    3330            <div class="form-group">
    3431                <label for="new-password">New Password</label>
    35                 <input type="password" id="new-password" name="new-password" required>
     32                <input type="password" id="new-password" required>
    3633                <small class="password-hint">At least 8 characters with uppercase, lowercase, number, and special character</small>
    3734            </div>
    … …  
    3936            <div class="form-group">
    4037                <label for="confirm-password">Confirm New Password</label>
    41                 <input type="password" id="confirm-password" name="confirm-password" required>
     38                <input type="password" id="confirm-password" required>
    4239            </div>
    4340
    44             <div class="form-group">
    45                 <button type="submit" class="btn-primary btn-full" id="submit-btn">Change Password</button>
    46             </div>
     41            <button type="submit" class="btn-primary">Change Password</button>
    4742        </form>
    4843    </div>
    … …  
    6257            </ul>
    6358        </div>
     59        <div class="footer-section">
     60            <h3>Contact</h3>
     61            <p>Email: support@handcraft.com</p>
     62        </div>
    6463    </div>
    6564    <div class="footer-bottom">
    … …  
    7069<script src="script.js"></script>
    7170<script>
    72     document.addEventListener('DOMContentLoaded', () => {
     71    document.addEventListener('DOMContentLoaded', async function() {
    7372        const urlParams = new URLSearchParams(window.location.search);
    74         const isForced = urlParams.get('forced') === 'true';
    75         let userType = 'admin'; // Default
     73        const forced = urlParams.get('forced');
     74        const redirect = urlParams.get('redirect');
    7675
    77         if (isForced) {
    78             document.getElementById('password-message').textContent =
    79                 'You must change your password before continuing.';
     76        // Check if user is authenticated for password change
     77        try {
     78            const user = await loadUserData();
     79            if (!user) {
     80                window.location.href = 'login.html';
     81                return;
     82            }
     83        } catch (error) {
     84            console.error('Error loading user:', error);
     85            window.location.href = 'login.html';
     86            return;
    8087        }
    8188
    82         const form = document.getElementById('change-password-form');
    83         const submitBtn = document.getElementById('submit-btn');
    84         const errorDiv = document.getElementById('error-message');
    85         const successDiv = document.getElementById('success-message');
     89        if (forced === 'true') {
     90            const messageDiv = document.getElementById('password-message');
     91            messageDiv.className = 'message warning';
     92            messageDiv.innerHTML = '⚠️ You are required to change your password before continuing.';
     93        }
    8694
    87         // Check if user is authenticated for password change and get user type
    88         checkAuthStatus();
     95        // Store redirect URL in session storage
     96        if (redirect) {
     97            sessionStorage.setItem('passwordChangeRedirect', redirect);
     98        }
    8999
    90         form.addEventListener('submit', async (e) => {
     100        // Handle form submission
     101        document.getElementById('change-password-form').addEventListener('submit', async function(e) {
    91102            e.preventDefault();
    92 
    93             // Clear previous messages
    94             errorDiv.style.display = 'none';
    95             successDiv.style.display = 'none';
    96 
    97             // Disable submit button to prevent double submission
    98             submitBtn.disabled = true;
    99             submitBtn.textContent = 'Changing Password...';
    100103
    101104            const newPassword = document.getElementById('new-password').value;
    102105            const confirmPassword = document.getElementById('confirm-password').value;
    103106
    104             // Client-side validation
    105             if (!newPassword || !confirmPassword) {
    106                 showError('All fields are required');
    107                 submitBtn.disabled = false;
    108                 submitBtn.textContent = 'Change Password';
     107            if (newPassword !== confirmPassword) {
     108                showMessage('Passwords do not match', 'error');
    109109                return;
    110110            }
    111111
    112             if (newPassword !== confirmPassword) {
    113                 showError('New passwords do not match');
    114                 submitBtn.disabled = false;
    115                 submitBtn.textContent = 'Change Password';
     112            // Password validation
     113            const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
     114            if (!passwordRegex.test(newPassword)) {
     115                showMessage('Password must have at least 8 characters, including uppercase, lowercase, number and special character', 'error');
    116116                return;
    117117            }
    118118
    119             // Validate password strength
    120             const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
    121             if (!passwordRegex.test(newPassword)) {
    122                 showError('Password must have at least 8 characters, including uppercase, lowercase, number and special character');
    123                 submitBtn.disabled = false;
    124                 submitBtn.textContent = 'Change Password';
    125                 return;
    126             }
    127 
    128             const formData = {
    129                 newPassword: newPassword,
    130                 confirmPassword: confirmPassword
    131             };
     119            // Get redirect from session storage or URL
     120            const redirectTo = sessionStorage.getItem('passwordChangeRedirect') || '';
    132121
    133122            try {
    134                 console.log('Sending password change request...');
    135123                const response = await fetch('/api/force-change-password', {
    136124                    method: 'POST',
    137                     headers: {
    138                         'Content-Type': 'application/json'
    139                     },
    140                     body: JSON.stringify(formData),
    141                     credentials: 'include' // Important: include cookies
     125                    headers: { 'Content-Type': 'application/json' },
     126                    body: JSON.stringify({
     127                        newPassword,
     128                        confirmPassword,
     129                        redirectTo: redirectTo
     130                    })
    142131                });
    143132
    144133                const data = await response.json();
    145                 console.log('Response:', data);
    146134
    147135                if (data.success) {
    148                     showSuccess('Password changed successfully! Redirecting...');
     136                    showMessage('Password changed successfully! Redirecting...', 'success');
     137                    sessionStorage.removeItem('passwordChangeRedirect');
    149138
    150                     // Clear form
    151                     form.reset();
    152 
    153                     // Redirect after short delay
     139                    // Redirect to appropriate dashboard
    154140                    setTimeout(() => {
    155141                        window.location.href = data.redirectTo || 'dashboard.html';
    156142                    }, 1500);
    157143                } else {
    158                     showError(data.message || 'Failed to change password');
    159                     submitBtn.disabled = false;
    160                     submitBtn.textContent = 'Change Password';
     144                    showMessage(data.message || 'Failed to change password', 'error');
    161145                }
    162146            } catch (error) {
    163                 console.error('Password change error:', error);
    164                 showError('Network error: ' + error.message);
    165                 submitBtn.disabled = false;
    166                 submitBtn.textContent = 'Change Password';
     147                console.error('Error changing password:', error);
     148                showMessage('An error occurred. Please try again.', 'error');
    167149            }
    168150        });
    169151
    170         async function checkAuthStatus() {
    171             try {
    172                 const response = await fetch('/api/user', {
    173                     credentials: 'include'
    174                 });
    175                 const data = await response.json();
    176 
    177                 if (!data.success) {
    178                     // Not authenticated, redirect to login
    179                     window.location.href = 'login.html';
    180                 } else if (data.isTempSession) {
    181                     console.log('Valid temporary session for password change');
    182                     if (data.user && data.user.userType) {
    183                         userType = data.user.userType;
    184                     }
    185                 } else {
    186                     // Already have full session, redirect to appropriate dashboard
    187                     if (data.user && data.user.userType) {
    188                         switch(data.user.userType) {
    189                             case 'admin':
    190                                 window.location.href = 'admin.html';
    191                                 break;
    192                             case 'store_owner':
    193                                 window.location.href = 'store-owner.html';
    194                                 break;
    195                             case 'store_employee':
    196                                 window.location.href = 'store-employee.html';
    197                                 break;
    198                             case 'client':
    199                                 window.location.href = 'client-dashboard.html';
    200                                 break;
    201                             default:
    202                                 window.location.href = 'dashboard.html';
    203                         }
    204                     }
    205                 }
    206             } catch (error) {
    207                 console.error('Auth check error:', error);
    208             }
    209         }
    210 
    211         function showError(message) {
    212             errorDiv.textContent = message;
    213             errorDiv.style.display = 'block';
    214             setTimeout(() => {
    215                 errorDiv.style.display = 'none';
    216             }, 5000);
    217         }
    218 
    219         function showSuccess(message) {
    220             successDiv.textContent = message;
    221             successDiv.style.display = 'block';
     152        function showMessage(msg, type) {
     153            const messageDiv = document.getElementById('password-message');
     154            messageDiv.className = 'message ' + type;
     155            messageDiv.textContent = msg;
    222156        }
    223157    });
  • interfejs/client-dashboard.html

    r4dff800 r79fff4f  
    1818      <li><a href="products.html">Products</a></li>
    1919      <li><a href="#" id="dashboard-link" class="active">My Dashboard</a></li>
     20      <li><a href="change-password.html" class="change-password-btn">🔑 Change Password</a></li>
     21      <li><a href="#" id="logout-link">Logout</a></li>
    2022    </ul>
    2123  </nav>
    … …  
    9698            <input type="text" id="new-address" required>
    9799          </div>
    98 
    99100          <div class="form-row">
    100101            <div class="form-group">
    … …  
    107108            </div>
    108109          </div>
    109 
    110110          <div class="form-group">
    111111            <label for="new-country">Country *</label>
    112112            <input type="text" id="new-country" required>
    113113          </div>
    114 
    115114          <div class="form-group checkbox">
    116115            <input type="checkbox" id="new-is-default">
    117116            <label for="new-is-default">Set as default address</label>
    118117          </div>
    119 
    120118          <button type="submit" class="btn-primary">Save Address</button>
    121119          <button type="button" class="btn-secondary" id="cancel-add-address">Cancel</button>
    … …  
    158156            </select>
    159157          </div>
    160 
    161158          <div class="form-group">
    162159            <label for="request-problem">Problem Description *</label>
    163160            <textarea id="request-problem" rows="4" required></textarea>
    164161          </div>
    165 
    166162          <button type="submit" class="btn-primary">Submit Request</button>
    167163          <button type="button" class="btn-secondary" id="cancel-new-request">Cancel</button>
    … …  
    262258  document.addEventListener('DOMContentLoaded', async () => {
    263259    const user = await loadUserData();
     260
    264261    if (!user || user.userType !== 'client') {
    265262      window.location.href = 'index.html';
    … …  
    268265
    269266    document.getElementById('client-name').textContent = `${user.firstName} ${user.lastName || ''}`;
     267
     268    // Logout functionality
     269    document.getElementById('logout-link').addEventListener('click', async (e) => {
     270      e.preventDefault();
     271      await logout();
     272    });
    270273
    271274    // Load profile data
    … …  
    297300        document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
    298301        document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
     302
    299303        btn.classList.add('active');
    300304        document.getElementById(`${btn.dataset.tab}-tab`).classList.add('active');
    … …  
    352356
    353357      const tbody = document.getElementById('orders-list');
     358
    354359      if (data.success && data.orders.length > 0) {
    355360        tbody.innerHTML = data.orders.map(order => {
    356361          const total = order.items ? order.items.reduce((sum, item) =>
    357362                  sum + (item.price * item.quantity), 0) : 0;
     363
    358364          return `
    359                             <tr>
    360                                 <td>${order.order_num}</td>
    361                                 <td>${order.store_name || 'Unknown'}</td>
    362                                 <td>${new Date(order.order_date).toLocaleDateString()}</td>
    363                                 <td><span class="status-badge status-${order.status}">${order.status}</span></td>
    364                                 <td>$${total.toFixed(2)}</td>
    365                                 <td>
    366                                     <button class="btn-small" onclick="viewOrder('${order.order_num}')">View</button>
    367                                     ${order.status === 'delivered' ?
     365                        <tr>
     366                            <td>${order.order_num}</td>
     367                            <td>${order.store_name || 'Unknown'}</td>
     368                            <td>${new Date(order.order_date).toLocaleDateString()}</td>
     369                            <td><span class="status-badge status-${order.status}">${order.status}</span></td>
     370                            <td>$${total.toFixed(2)}</td>
     371                            <td>
     372                                <button class="btn-small" onclick="viewOrder('${order.order_num}')">View</button>
     373                                ${order.status === 'delivered' ?
    368374                  `<button class="btn-small" onclick="reviewOrder('${order.order_num}')">Review</button>` : ''}
    369                                 </td>
    370                             </tr>
    371                         `;
     375                            </td>
     376                        </tr>
     377                    `;
    372378        }).join('');
    373379      } else {
    … …  
    383389    // This would need a separate API endpoint
    384390    document.getElementById('addresses-list').innerHTML = `
    385                 <div class="address-card">
    386                     <p><strong>Default Address:</strong></p>
    387                     <p>st. Center num.10, Skopje 1000, North Macedonia</p>
    388                     <button class="btn-small">Edit</button>
    389                     <button class="btn-small" style="background: var(--danger);">Delete</button>
    390                 </div>
    391             `;
     391            <div class="address-card">
     392                <p><strong>Default Address:</strong></p>
     393                <p>st. Center num.10, Skopje 1000, North Macedonia</p>
     394                <button class="btn-small">Edit</button>
     395                <button class="btn-small" style="background: var(--danger);">Delete</button>
     396            </div>
     397        `;
    392398  }
    393399
  • interfejs/store-employee.html

    r4dff800 r79fff4f  
    1818            <li><a href="products.html">Products</a></li>
    1919            <li><a href="#" id="dashboard-link" class="active">Employee</a></li>
     20            <li><a href="change-password.html" class="change-password-btn">🔑 Change Password</a></li>
     21            <li><a href="#" id="logout-link">Logout</a></li>
    2022        </ul>
    2123    </nav>
    … …  
    170172</main>
    171173
     174<!-- Respond to Request Modal -->
    172175<div id="respond-request-modal" class="modal" style="display: none;">
    173176    <div class="modal-content">
    … …  
    176179        <form id="respond-request-form" class="form">
    177180            <input type="hidden" id="respond-request-num">
    178 
    179181            <div class="form-group">
    180182                <label for="request-response">Your Response</label>
    181183                <textarea id="request-response" rows="4" required></textarea>
    182184            </div>
    183 
    184185            <div class="form-group">
    185186                <label for="request-status">Update Status</label>
    … …  
    190191                </select>
    191192            </div>
    192 
    193193            <button type="submit" class="btn-primary">Submit Response</button>
    194194        </form>
    … …  
    196196</div>
    197197
     198<!-- Process Refund Modal -->
    198199<div id="process-refund-modal" class="modal" style="display: none;">
    199200    <div class="modal-content">
    … …  
    202203        <form id="process-refund-form" class="form">
    203204            <input type="hidden" id="process-refund-id">
    204 
    205205            <div class="form-group">
    206206                <label for="refund-action">Action</label>
    … …  
    210210                </select>
    211211            </div>
    212 
    213212            <div class="form-group">
    214213                <label for="refund-notes">Notes</label>
    215214                <textarea id="refund-notes" rows="3"></textarea>
    216215            </div>
    217 
    218216            <button type="submit" class="btn-primary">Process Refund</button>
    219217        </form>
    … …  
    244242    document.addEventListener('DOMContentLoaded', async () => {
    245243        const user = await loadUserData();
     244
    246245        if (!user || user.userType !== 'store_employee') {
    247246            window.location.href = 'index.html';
    … …  
    250249
    251250        document.getElementById('employee-name').textContent = `${user.firstName} ${user.lastName || ''}`;
     251
     252        // Logout functionality
     253        document.getElementById('logout-link').addEventListener('click', async (e) => {
     254            e.preventDefault();
     255            await logout();
     256        });
    252257
    253258        // Load stores
    … …  
    277282                document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
    278283                document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
     284
    279285                btn.classList.add('active');
    280286                document.getElementById(`${btn.dataset.tab}-tab`).classList.add('active');
    … …  
    316322                // Display tasks
    317323                const tasksList = document.getElementById('tasks-list');
     324
    318325                if (data.tasks.pending_orders.length > 0 || data.tasks.pending_requests.length > 0 || data.tasks.pending_refunds.length > 0) {
    319326                    let tasksHtml = '<div class="task-items">';
    … …  
    323330                        data.tasks.pending_orders.forEach(order => {
    324331                            tasksHtml += `
    325                                     <div class="task-item">
    326                                         <p><strong>Order #${order.order_num}</strong> - ${order.first_name} ${order.last_name}</p>
    327                                         <button class="btn-small" onclick="updateOrderStatus('${order.order_num}')">Update Status</button>
    328                                     </div>
    329                                 `;
     332                                <div class="task-item">
     333                                    <p><strong>Order #${order.order_num}</strong> - ${order.first_name} ${order.last_name}</p>
     334                                    <button class="btn-small" onclick="updateOrderStatus('${order.order_num}')">Update Status</button>
     335                                </div>
     336                            `;
    330337                        });
    331338                    }
    … …  
    335342                        data.tasks.pending_requests.forEach(request => {
    336343                            tasksHtml += `
    337                                     <div class="task-item">
    338                                         <p><strong>Request #${request.request_num}</strong> - ${request.first_name} ${request.last_name}</p>
    339                                         <p>${request.problem.substring(0, 50)}${request.problem.length > 50 ? '...' : ''}</p>
    340                                         <button class="btn-small" onclick="respondToRequest('${request.request_num}')">Respond</button>
    341                                     </div>
    342                                 `;
     344                                <div class="task-item">
     345                                    <p><strong>Request #${request.request_num}</strong> - ${request.first_name} ${request.last_name}</p>
     346                                    <p>${request.problem.substring(0, 50)}${request.problem.length > 50 ? '...' : ''}</p>
     347                                    <button class="btn-small" onclick="respondToRequest('${request.request_num}')">Respond</button>
     348                                </div>
     349                            `;
    343350                        });
    344351                    }
    … …  
    348355                        data.tasks.pending_refunds.forEach(refund => {
    349356                            tasksHtml += `
    350                                     <div class="task-item">
    351                                         <p><strong>Refund #${refund.refund_id}</strong> - Order #${refund.order_num}</p>
    352                                         <p>Amount: $${parseFloat(refund.amount).toFixed(2)}</p>
    353                                         <button class="btn-small" onclick="processRefund('${refund.refund_id}')">Process</button>
    354                                     </div>
    355                                 `;
     357                                <div class="task-item">
     358                                    <p><strong>Refund #${refund.refund_id}</strong> - Order #${refund.order_num}</p>
     359                                    <p>Amount: $${parseFloat(refund.amount).toFixed(2)}</p>
     360                                    <button class="btn-small" onclick="processRefund('${refund.refund_id}')">Process</button>
     361                                </div>
     362                            `;
    356363                        });
    357364                    }
    … …  
    374381
    375382            const tbody = document.getElementById('orders-list');
     383
    376384            if (data.success && data.orders.length > 0) {
    377385                tbody.innerHTML = data.orders.map(order => {
    378386                    const total = order.items ? order.items.reduce((sum, item) =>
    379387                        sum + (item.price * item.quantity), 0) : 0;
     388
    380389                    return `
    381                             <tr>
    382                                 <td>${order.order_num}</td>
    383                                 <td>${order.first_name} ${order.last_name}</td>
    384                                 <td>${new Date(order.order_date).toLocaleDateString()}</td>
    385                                 <td><span class="status-badge status-${order.status}">${order.status}</span></td>
    386                                 <td>$${total.toFixed(2)}</td>
    387                                 <td>
    388                                     <button class="btn-small" onclick="updateOrderStatus('${order.order_num}')">Update</button>
    389                                     <button class="btn-small" onclick="viewOrderDetails('${order.order_num}')">View</button>
    390                                 </td>
    391                             </tr>
    392                         `;
     390                        <tr>
     391                            <td>${order.order_num}</td>
     392                            <td>${order.first_name} ${order.last_name}</td>
     393                            <td>${new Date(order.order_date).toLocaleDateString()}</td>
     394                            <td><span class="status-badge status-${order.status}">${order.status}</span></td>
     395                            <td>$${total.toFixed(2)}</td>
     396                            <td>
     397                                <button class="btn-small" onclick="updateOrderStatus('${order.order_num}')">Update</button>
     398                                <button class="btn-small" onclick="viewOrderDetails('${order.order_num}')">View</button>
     399                            </td>
     400                        </tr>
     401                    `;
    393402                }).join('');
    394403            } else {
    … …  
    417426
    418427            const tbody = document.getElementById('products-list');
     428
    419429            if (data.success && data.products.length > 0) {
    420430                tbody.innerHTML = data.products.map(product => `
    421                         <tr>
    422                             <td>${product.code}</td>
    423                             <td>${product.description.substring(0, 30)}${product.description.length > 30 ? '...' : ''}</td>
    424                             <td>$${parseFloat(product.price).toFixed(2)}</td>
    425                             <td>${product.availability}</td>
    426                             <td>
    427                                 <button class="btn-small" onclick="viewProduct('${product.code}')">View</button>
    428                             </td>
    429                         </tr>
    430                     `).join('');
     431                    <tr>
     432                        <td>${product.code}</td>
     433                        <td>${product.description.substring(0, 30)}${product.description.length > 30 ? '...' : ''}</td>
     434                        <td>$${parseFloat(product.price).toFixed(2)}</td>
     435                        <td>${product.availability}</td>
     436                        <td>
     437                            <button class="btn-small" onclick="viewProduct('${product.code}')">View</button>
     438                        </td>
     439                    </tr>
     440                `).join('');
    431441            } else {
    432442                tbody.innerHTML = '<tr><td colspan="5">No products found</td></tr>';
  • interfejs/store-owner.html

    r4dff800 r79fff4f  
    1818            <li><a href="products.html">Products</a></li>
    1919            <li><a href="#" id="dashboard-link" class="active">Store Owner</a></li>
     20            <li><a href="change-password.html" class="change-password-btn">🔑 Change Password</a></li>
     21            <li><a href="#" id="logout-link">Logout</a></li>
    2022        </ul>
    2123    </nav>
    … …  
    457459        document.getElementById('owner-name').textContent = `${user.firstName} ${user.lastName || ''}`;
    458460
     461        // Logout functionality
     462        document.getElementById('logout-link').addEventListener('click', async (e) => {
     463            e.preventDefault();
     464            await logout();
     465        });
     466
    459467        // Load stores
    460468        const stores = user.stores || [];
    … …  
    484492                document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
    485493                document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
     494
    486495                btn.classList.add('active');
    487496                document.getElementById(`${btn.dataset.tab}-tab`).classList.add('active');
    … …  
    558567            const response = await fetch(`/api/store-products?storeId=${storeId}`);
    559568            const data = await response.json();
     569
    560570            const tbody = document.getElementById('products-list');
    561571
    562572            if (data.success && data.products.length > 0) {
    563573                tbody.innerHTML = data.products.map(product => `
    564                         <tr>
    565                             <td>${product.code}</td>
    566                             <td>${product.description.substring(0, 30)}${product.description.length > 30 ? '...' : ''}</td>
    567                             <td>$${parseFloat(product.price).toFixed(2)}</td>
    568                             <td>${product.availability}</td>
    569                             <td>${product.category_name || 'General'}</td>
    570                             <td>
    571                                 <button class="btn-small" onclick="editProduct('${product.code}')">Edit</button>
    572                                 <button class="btn-small" style="background: var(--danger);" onclick="deleteProduct('${product.code}', '${storeId}')">Delete</button>
    573                             </td>
    574                         </tr>
    575                     `).join('');
     574                    <tr>
     575                        <td>${product.code}</td>
     576                        <td>${product.description.substring(0, 30)}${product.description.length > 30 ? '...' : ''}</td>
     577                        <td>$${parseFloat(product.price).toFixed(2)}</td>
     578                        <td>${product.availability}</td>
     579                        <td>${product.category_name || 'General'}</td>
     580                        <td>
     581                            <button class="btn-small" onclick="editProduct('${product.code}')">Edit</button>
     582                            <button class="btn-small" style="background: var(--danger);" onclick="deleteProduct('${product.code}', '${storeId}')">Delete</button>
     583                        </td>
     584                    </tr>
     585                `).join('');
    576586            } else {
    577587                tbody.innerHTML = '<tr><td colspan="6">No products found</td></tr>';
    … …  
    587597            const response = await fetch(`/api/store-orders?storeId=${storeId}`);
    588598            const data = await response.json();
     599
    589600            const tbody = document.getElementById('orders-list');
    590601
    … …  
    593604                    const total = order.items ? order.items.reduce((sum, item) =>
    594605                        sum + (item.price * item.quantity), 0) : 0;
     606
    595607                    return `
    596                             <tr>
    597                                 <td>${order.order_num}</td>
    598                                 <td>${order.first_name} ${order.last_name}</td>
    599                                 <td>${new Date(order.order_date).toLocaleDateString()}</td>
    600                                 <td><span class="status-badge status-${order.status}">${order.status}</span></td>
    601                                 <td>$${total.toFixed(2)}</td>
    602                                 <td>
    603                                     <button class="btn-small" onclick="viewOrder('${order.order_num}')">View</button>
    604                                 </td>
    605                             </tr>
    606                         `;
     608                        <tr>
     609                            <td>${order.order_num}</td>
     610                            <td>${order.first_name} ${order.last_name}</td>
     611                            <td>${new Date(order.order_date).toLocaleDateString()}</td>
     612                            <td><span class="status-badge status-${order.status}">${order.status}</span></td>
     613                            <td>$${total.toFixed(2)}</td>
     614                            <td>
     615                                <button class="btn-small" onclick="viewOrder('${order.order_num}')">View</button>
     616                            </td>
     617                        </tr>
     618                    `;
    607619                }).join('');
    608620            } else {
    … …  
    619631            const response = await fetch(`/api/store-employees?storeId=${storeId}`);
    620632            const data = await response.json();
     633
    621634            const tbody = document.getElementById('employees-list');
    622635
    623636            if (data.success && data.employees.length > 0) {
    624637                tbody.innerHTML = data.employees.map(emp => `
    625                         <tr>
    626                             <td>${emp.id}</td>
    627                             <td>${emp.first_name} ${emp.last_name}</td>
    628                             <td>${emp.email}</td>
    629                             <td>${emp.date_of_hire || 'N/A'}</td>
    630                             <td><span class="status-badge">${emp.permission_type || 'EMPLOYEE'}</span></td>
    631                             <td>
    632                                 <button class="btn-small" onclick="editEmployee('${emp.id}')">Edit</button>
    633                                 <button class="btn-small" style="background: var(--danger);" onclick="deleteEmployee('${emp.id}', '${storeId}')">Delete</button>
    634                             </td>
    635                         </tr>
    636                     `).join('');
     638                    <tr>
     639                        <td>${emp.id}</td>
     640                        <td>${emp.first_name} ${emp.last_name}</td>
     641                        <td>${emp.email}</td>
     642                        <td>${emp.date_of_hire || 'N/A'}</td>
     643                        <td><span class="status-badge">${emp.permission_type || 'EMPLOYEE'}</span></td>
     644                        <td>
     645                            <button class="btn-small" onclick="editEmployee('${emp.id}')">Edit</button>
     646                            <button class="btn-small" style="background: var(--danger);" onclick="deleteEmployee('${emp.id}', '${storeId}')">Delete</button>
     647                        </td>
     648                    </tr>
     649                `).join('');
    637650            } else {
    638651                tbody.innerHTML = '<tr><td colspan="6">No employees found</td></tr>';
    … …  
    661674                    `<option value="${cat.category_id}">${cat.name}</option>`
    662675                ).join('');
     676
    663677                document.getElementById('category-parent').innerHTML = '<option value="">None (Top Level Category)</option>' + parentOptions;
    664678            }
    … …  
    787801                document.getElementById('add-product-form').reset();
    788802                loadProducts(storeId);
     803
    789804                // Switch to products tab
    790805                document.querySelector('[data-tab="products"]').click();
    … …  
    839854                document.getElementById('add-employee-form').reset();
    840855                loadEmployees(storeId);
     856
    841857                // Switch to employees tab
    842858                document.querySelector('[data-tab="employees"]').click();
    … …  
    10611077
    10621078        document.getElementById('report-results').innerHTML = `
    1063                 <div class="dashboard-section">
    1064                     <h4>Generating Report...</h4>
    1065                     <div class="loading">Please wait</div>
    1066                 </div>
    1067             `;
     1079            <div class="dashboard-section">
     1080                <h4>Generating Report...</h4>
     1081                <div class="loading">Please wait</div>
     1082            </div>
     1083        `;
    10681084
    10691085        try {
    … …  
    10841100            if (data.success) {
    10851101                document.getElementById('report-results').innerHTML = `
    1086                         <div class="dashboard-section">
    1087                             <h4>Report Generated Successfully</h4>
    1088                             <p><strong>Report ID:</strong> ${data.reportId}</p>
    1089                             <p><strong>Period:</strong> ${data.report.period}</p>
    1090                             <p><strong>Date Range:</strong> ${data.report.startDate} to ${data.report.endDate}</p>
    1091                             <p><strong>Type:</strong> ${data.report.type}</p>
    1092                             <p><strong>Generated:</strong> ${new Date(data.report.generatedAt).toLocaleString()}</p>
    1093                             <button class="btn-small" onclick="downloadReport('${data.reportId}')">Download Report</button>
    1094                         </div>
    1095                     `;
     1102                    <div class="dashboard-section">
     1103                        <h4>Report Generated Successfully</h4>
     1104                        <p><strong>Report ID:</strong> ${data.reportId}</p>
     1105                        <p><strong>Period:</strong> ${data.report.period}</p>
     1106                        <p><strong>Date Range:</strong> ${data.report.startDate} to ${data.report.endDate}</p>
     1107                        <p><strong>Type:</strong> ${data.report.type}</p>
     1108                        <p><strong>Generated:</strong> ${new Date(data.report.generatedAt).toLocaleString()}</p>
     1109                        <button class="btn-small" onclick="downloadReport('${data.reportId}')">Download Report</button>
     1110                    </div>
     1111                `;
    10961112            } else {
    10971113                document.getElementById('report-results').innerHTML = `
    1098                         <div class="dashboard-section">
    1099                             <p class="error">Failed to generate report: ${data.message}</p>
    1100                         </div>
    1101                     `;
     1114                    <div class="dashboard-section">
     1115                        <p class="error">Failed to generate report: ${data.message}</p>
     1116                    </div>
     1117                `;
    11021118            }
    11031119        } catch (error) {
    11041120            console.error('Error generating report:', error);
    11051121            document.getElementById('report-results').innerHTML = `
    1106                     <div class="dashboard-section">
    1107                         <p class="error">An error occurred while generating the report</p>
    1108                     </div>
    1109                 `;
     1122                <div class="dashboard-section">
     1123                    <p class="error">An error occurred while generating the report</p>
     1124                </div>
     1125            `;
    11101126        }
    11111127    }
  • server.js

    r4dff800 r79fff4f  
    1010
    1111const port = process.env.PORT || 3000;
     12
    1213const sessions = new Map();
    1314const verificationCodes = new Map();
    … …  
    3132        }
    3233    };
     34
    3335    emailTransporter = nodemailer.createTransport(emailConfig);
     36
    3437    emailTransporter.verify(function(error, success) {
    3538        if (error) {
    … …  
    5255                const codeMatch = mailOptions.html.match(/\b\d{6}\b/);
    5356                const code = codeMatch ? codeMatch[0] : 'unknown';
     57
    5458                console.log('');
    5559                console.log('🎯 ===== VERIFICATION CODE =====');
    … …  
    6064                console.log('================================');
    6165                console.log('');
     66
    6267                resolve({ messageId: 'dev-' + Date.now() });
    6368            });
    … …  
    932937                    }
    933938                    rolesInserted++;
     939
    934940                    if (rolesInserted === roles.length) {
    935941                        console.log('✅ Roles inserted');
    936 
    937942                        // Create admin user with ID 000000
    938943                        createAdminUser();
    … …  
    11511156                // Check if store owner or employee
    11521157                const personalId = userId.replace('personal_', '');
     1158
    11531159                database.database.get(
    11541160                    'SELECT boss_id FROM boss WHERE boss_id = ?',
    … …  
    12011207            body += chunk.toString();
    12021208        });
    1203 
    12041209        req.on('end', () => {
    12051210            const { username, email, password, userType, firstName, lastName } = JSON.parse(body);
    … …  
    12661271                            console.log('✅ Verification email sent to:', email);
    12671272                            database.logAudit(null, 'REGISTER_ATTEMPT', 'user', null, `Registration attempt for ${email} as ${userType}`, ipAddress);
    1268 
    12691273                            res.writeHead(200, { 'Content-Type': 'application/json' });
    12701274                            res.end(JSON.stringify({
    … …  
    12941298            body += chunk.toString();
    12951299        });
    1296 
    12971300        req.on('end', () => {
    12981301            const formData = JSON.parse(body);
    … …  
    13251328
    13261329            const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
     1330
    13271331            if (!emailRegex.test(formData.ownerEmail)) {
    13281332                res.writeHead(400, { 'Content-Type': 'application/json' });
    … …  
    14061410                                // Next store number is max + 1, starting from 1 if no stores exist
    14071411                                let nextStoreNumber = 1;
     1412
    14081413                                if (result && result.max_store_num) {
    14091414                                    // Extract numeric part from store_id (format: XXX)
    … …  
    14611466                                        console.log('✅ Store registration email sent to:', formData.ownerEmail);
    14621467                                        database.logAudit(null, 'STORE_REGISTER_ATTEMPT', 'store', null, `Store registration attempt: ${formData.storeName}`, ipAddress);
    1463 
    14641468                                        res.writeHead(200, { 'Content-Type': 'application/json' });
    14651469                                        res.end(JSON.stringify({
    … …  
    14941498            body += chunk.toString();
    14951499        });
    1496 
    14971500        req.on('end', () => {
    14981501            const { firstName, lastName, email, password, address, city, postcode, country, isDefaultAddress } = JSON.parse(body);
    … …  
    15591562                        console.log('✅ Verification email sent to:', email);
    15601563                        database.logAudit(null, 'CLIENT_REGISTER_ATTEMPT', 'client', null, `Client registration attempt for ${email}`, ipAddress);
    1561 
    15621564                        res.writeHead(200, { 'Content-Type': 'application/json' });
    15631565                        res.end(JSON.stringify({
    … …  
    15861588            body += chunk.toString();
    15871589        });
    1588 
    15891590        req.on('end', () => {
    15901591            const { email } = JSON.parse(body);
    … …  
    17211722            body += chunk.toString();
    17221723        });
    1723 
    17241724        req.on('end', () => {
    17251725            const { email, code } = JSON.parse(body);
    … …  
    17931793                                        database.database.run('ROLLBACK');
    17941794                                        console.error('Error inserting personal:', err);
     1795
    17951796                                        if (err.code === '23505') {
    17961797                                            res.writeHead(400, { 'Content-Type': 'application/json' });
    … …  
    18411842                                                            }
    18421843
    1843                                                             database.database.run('COMMIT', (commitErr) => {
    1844                                                                 if (commitErr) {
    1845                                                                     console.error('Error committing transaction:', commitErr);
    1846                                                                     database.database.run('ROLLBACK');
    1847                                                                     res.writeHead(500, { 'Content-Type': 'application/json' });
    1848                                                                     res.end(JSON.stringify({ success: false, message: 'Error completing registration' }));
    1849                                                                     return;
     1844                                                            // Also create entry in users table for login with force_password_change = 1
     1845                                                            database.database.run(
     1846                                                                'INSERT INTO users (id, username, email, password, user_type, force_password_change) VALUES (?, ?, ?, ?, ?, ?)',
     1847                                                                [
     1848                                                                    tempStoreData.personalId,
     1849                                                                    `${tempStoreData.ownerFirstName} ${tempStoreData.ownerLastName}`,
     1850                                                                    tempStoreData.ownerEmail,
     1851                                                                    bcrypt.hashSync(tempStoreData.password, 10),
     1852                                                                    'store_owner',
     1853                                                                    1
     1854                                                                ],
     1855                                                                (err) => {
     1856                                                                    if (err) {
     1857                                                                        console.error('Error creating user entry for store owner:', err);
     1858                                                                    }
     1859
     1860                                                                    database.database.run('COMMIT', (commitErr) => {
     1861                                                                        if (commitErr) {
     1862                                                                            console.error('Error committing transaction:', commitErr);
     1863                                                                            database.database.run('ROLLBACK');
     1864                                                                            res.writeHead(500, { 'Content-Type': 'application/json' });
     1865                                                                            res.end(JSON.stringify({ success: false, message: 'Error completing registration' }));
     1866                                                                            return;
     1867                                                                        }
     1868
     1869                                                                        tempStoreRegistrations.delete(code);
     1870                                                                        verificationCodes.delete(email);
     1871
     1872                                                                        console.log(`✅ Store registration completed successfully:`);
     1873                                                                        console.log(`   Store ID: ${tempStoreData.storeId}`);
     1874                                                                        console.log(`   Store Name: ${tempStoreData.storeName}`);
     1875                                                                        console.log(`   Personal ID: ${tempStoreData.personalId}`);
     1876                                                                        console.log(`   Owner: ${tempStoreData.ownerFirstName} ${tempStoreData.ownerLastName}`);
     1877
     1878                                                                        database.logAudit(tempStoreData.personalId, 'STORE_REGISTER_SUCCESS', 'store', tempStoreData.storeId, `Store registered: ${tempStoreData.storeName}`, ipAddress);
     1879
     1880                                                                        res.writeHead(200, { 'Content-Type': 'application/json' });
     1881                                                                        res.end(JSON.stringify({
     1882                                                                            success: true,
     1883                                                                            message: 'Store registration successful! You can now login.',
     1884                                                                            storeId: tempStoreData.storeId,
     1885                                                                            storeIdPadded: tempStoreData.storeIdPadded,
     1886                                                                            storeName: tempStoreData.storeName,
     1887                                                                            personalId: tempStoreData.personalId,
     1888                                                                            userType: 'store_owner',
     1889                                                                            redirectTo: 'login.html'
     1890                                                                        }));
     1891                                                                    });
    18501892                                                                }
    1851 
    1852                                                                 tempStoreRegistrations.delete(code);
    1853                                                                 verificationCodes.delete(email);
    1854 
    1855                                                                 console.log(`✅ Store registration completed successfully:`);
    1856                                                                 console.log(`   Store ID: ${tempStoreData.storeId}`);
    1857                                                                 console.log(`   Store Name: ${tempStoreData.storeName}`);
    1858                                                                 console.log(`   Personal ID: ${tempStoreData.personalId}`);
    1859                                                                 console.log(`   Owner: ${tempStoreData.ownerFirstName} ${tempStoreData.ownerLastName}`);
    1860 
    1861                                                                 database.logAudit(tempStoreData.personalId, 'STORE_REGISTER_SUCCESS', 'store', tempStoreData.storeId, `Store registered: ${tempStoreData.storeName}`, ipAddress);
    1862 
    1863                                                                 res.writeHead(200, { 'Content-Type': 'application/json' });
    1864                                                                 res.end(JSON.stringify({
    1865                                                                     success: true,
    1866                                                                     message: 'Store registration successful! You can now login.',
    1867                                                                     storeId: tempStoreData.storeId,
    1868                                                                     storeIdPadded: tempStoreData.storeIdPadded,
    1869                                                                     storeName: tempStoreData.storeName,
    1870                                                                     personalId: tempStoreData.personalId,
    1871                                                                     userType: 'store_owner',
    1872                                                                     redirectTo: 'login.html'
    1873                                                                 }));
    1874                                                             });
     1893                                                            );
    18751894                                                        }
    18761895                                                    );
    … …  
    19521971            } else {
    19531972                const userId = 'user_' + Date.now().toString().slice(-8);
     1973
    19541974                database.createUser(userId, tempUserData.username, tempUserData.email, tempUserData.password, tempUserData.userType, (err, userId) => {
    19551975                    if (err) {
    … …  
    19822002            body += chunk.toString();
    19832003        });
    1984 
    19852004        req.on('end', () => {
    19862005            const { email, password } = JSON.parse(body);
    … …  
    20032022
    20042023                        const twoFACode = generateVerificationCode();
    2005 
    20062024                        verificationCodes.set(adminUser.email, {
    20072025                            code: twoFACode,
    … …  
    20482066                    }
    20492067                });
     2068
    20502069                return;
    20512070            }
    … …  
    20942113                            'Set-Cookie': `sessionId=${sessionId}; HttpOnly; Path=/; Max-Age=3600; SameSite=Strict`
    20952114                        });
     2115
    20962116                        res.end(JSON.stringify({
    20972117                            success: true,
    … …  
    21552175
    21562176                                                const twoFACode = generateVerificationCode();
    2157 
    21582177                                                verificationCodes.set(personal.email, {
    21592178                                                    code: twoFACode,
    … …  
    22162235
    22172236                                                        const twoFACode = generateVerificationCode();
    2218 
    22192237                                                        verificationCodes.set(personal.email, {
    22202238                                                            code: twoFACode,
    … …  
    22782296
    22792297                                                                const twoFACode = generateVerificationCode();
    2280 
    22812298                                                                verificationCodes.set(userByUsername.email, {
    22822299                                                                    code: twoFACode,
    … …  
    23292346
    23302347                                                        const twoFACode = generateVerificationCode();
    2331 
    23322348                                                        verificationCodes.set(user.email, {
    23332349                                                            code: twoFACode,
    … …  
    23962412            body += chunk.toString();
    23972413        });
    2398 
    23992414        req.on('end', () => {
    24002415            const { email } = JSON.parse(body);
    … …  
    24192434
    24202435                            const newTwoFACode = generateVerificationCode();
    2421 
    24222436                            verificationCodes.set(userByUsername.email, {
    24232437                                code: newTwoFACode,
    … …  
    24562470
    24572471                    const newTwoFACode = generateVerificationCode();
    2458 
    24592472                    verificationCodes.set(user.email, {
    24602473                        code: newTwoFACode,
    … …  
    24972510            body += chunk.toString();
    24982511        });
    2499 
    25002512        req.on('end', () => {
    25012513            const { email, code } = JSON.parse(body);
    … …  
    25322544                verificationCodes.delete(email);
    25332545
     2546                // Determine redirect based on user type
     2547                let redirectTo = 'change-password.html?forced=true';
     2548                if (verificationData.userType === 'store_owner') {
     2549                    redirectTo = 'change-password.html?forced=true&redirect=store-owner.html';
     2550                } else if (verificationData.userType === 'store_employee') {
     2551                    redirectTo = 'change-password.html?forced=true&redirect=store-employee.html';
     2552                } else if (verificationData.userType === 'admin') {
     2553                    redirectTo = 'change-password.html?forced=true&redirect=admin.html';
     2554                } else if (verificationData.userType === 'client') {
     2555                    redirectTo = 'change-password.html?forced=true&redirect=client-dashboard.html';
     2556                }
     2557
    25342558                res.writeHead(200, {
    25352559                    'Content-Type': 'application/json',
    25362560                    'Set-Cookie': `sessionId=${tempSessionId}; HttpOnly; Path=/; Max-Age=3600; SameSite=Strict`
    25372561                });
     2562
    25382563                res.end(JSON.stringify({
    25392564                    success: true,
    … …  
    25412566                    requiresPasswordChange: true,
    25422567                    userType: verificationData.userType,
    2543                     redirectTo: 'change-password.html?forced=true'
     2568                    redirectTo: redirectTo
    25442569                }));
    25452570
    … …  
    25902615                'Set-Cookie': `sessionId=${sessionId}; HttpOnly; Path=/; Max-Age=3600; SameSite=Strict`
    25912616            });
     2617
    25922618            res.end(JSON.stringify({
    25932619                success: true,
    … …  
    26162642            'Set-Cookie': 'sessionId=; HttpOnly; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Strict'
    26172643        });
     2644
    26182645        res.end(JSON.stringify({ success: true, message: 'Successfully logged out' }));
    26192646    }
    … …  
    27362763                });
    27372764            }
    2738 
    27392765            else if (userIdStr.startsWith('personal_')) {
    27402766                const personalId = userIdStr.replace('personal_', '');
    … …  
    28852911                body += chunk.toString();
    28862912            });
    2887 
    28882913            req.on('end', () => {
    28892914                const categoryData = JSON.parse(body);
    … …  
    29682993                body += chunk.toString();
    29692994            });
    2970 
    29712995            req.on('end', () => {
    29722996                const orderData = JSON.parse(body);
    … …  
    30663090                body += chunk.toString();
    30673091            });
    3068 
    30693092            req.on('end', () => {
    30703093                const reviewData = JSON.parse(body);
    … …  
    30733096                if (userIdStr.startsWith('client_')) {
    30743097                    const clientId = parseInt(userIdStr.replace('client_', ''));
    3075 
    30763098                    reviewData.client_id = clientId;
    30773099
    … …  
    31003122                body += chunk.toString();
    31013123            });
    3102 
    31033124            req.on('end', () => {
    31043125                const requestData = JSON.parse(body);
    … …  
    31703191                body += chunk.toString();
    31713192            });
    3172 
    31733193            req.on('end', () => {
    31743194                const refundData = JSON.parse(body);
    … …  
    32403260                body += chunk.toString();
    32413261            });
    3242 
    32433262            req.on('end', () => {
    32443263                const productData = JSON.parse(body);
    … …  
    33333352                body += chunk.toString();
    33343353            });
    3335 
    33363354            req.on('end', () => {
    33373355                const productData = JSON.parse(body);
    … …  
    34273445    }
    34283446
     3447    // Updated /api/force-change-password endpoint with redirect handling
    34293448    else if (pathname === '/api/force-change-password' && req.method === 'POST') {
    34303449        const cookies = parseCookies(req);
    … …  
    34393458
    34403459        let body = '';
    3441 
    34423460        req.on('data', chunk => {
    34433461            body += chunk.toString();
    34443462        });
    3445 
    34463463        req.on('end', () => {
    34473464            try {
    3448                 const { newPassword, confirmPassword } = JSON.parse(body);
     3465                const { newPassword, confirmPassword, redirectTo } = JSON.parse(body);
    34493466
    34503467                if (!newPassword || !confirmPassword) {
    … …  
    35083525                                // Create new permanent session
    35093526                                const newSessionId = generateSessionId();
    3510                                 sessions.set(newSessionId, String(userId));
    3511 
    3512                                 // Determine redirect based on user type
    3513                                 let redirectTo = 'dashboard.html';
    3514 
    3515                                 if (user.username === 'admin' || user.user_type === 'admin') {
    3516                                     redirectTo = 'admin.html';
    3517                                 } else if (user.user_type === 'store_owner') {
    3518                                     redirectTo = 'store-owner.html';
    3519                                 } else if (user.user_type === 'store_employee') {
    3520                                     redirectTo = 'store-employee.html';
    3521                                 } else if (user.user_type === 'client') {
    3522                                     redirectTo = 'client-dashboard.html';
     3527
     3528                                // Determine how to store the user ID based on user type
     3529                                let sessionUserId = String(userId);
     3530
     3531                                if (user.user_type === 'store_owner' || user.user_type === 'store_employee') {
     3532                                    sessionUserId = `personal_${userId}`;
    35233533                                }
    35243534
    3525                                 console.log(`Password changed successfully for user ${userId}, redirecting to ${redirectTo}`);
     3535                                sessions.set(newSessionId, sessionUserId);
     3536
     3537                                // Determine redirect based on user type or provided redirectTo
     3538                                let finalRedirect = redirectTo || 'dashboard.html';
     3539
     3540                                if (!redirectTo) {
     3541                                    if (user.username === 'admin' || user.user_type === 'admin') {
     3542                                        finalRedirect = 'admin.html';
     3543                                    } else if (user.user_type === 'store_owner') {
     3544                                        finalRedirect = 'store-owner.html';
     3545                                    } else if (user.user_type === 'store_employee') {
     3546                                        finalRedirect = 'store-employee.html';
     3547                                    } else if (user.user_type === 'client') {
     3548                                        finalRedirect = 'client-dashboard.html';
     3549                                    }
     3550                                }
     3551
     3552                                console.log(`Password changed successfully for user ${userId}, redirecting to ${finalRedirect}`);
    35263553
    35273554                                database.logAudit(userId, 'FORCED_PASSWORD_CHANGE', 'auth', userId.toString(),
    … …  
    35313558                                res.writeHead(200, {
    35323559                                    'Content-Type': 'application/json',
    3533                                     'Set-Cookie': `sessionId=${newSessionId}; HttpOnly; Path=/; Max-Age=3600; SameSite=Strict`
     3560                                    'Set-Cookie': `sessionId=${newSessionId}; HttpOnly; Path=/; Max-Age=86400; SameSite=Strict` // Extended to 24 hours
    35343561                                });
     3562
    35353563                                res.end(JSON.stringify({
    35363564                                    success: true,
    35373565                                    message: 'Password changed successfully.',
    3538                                     redirectTo: redirectTo,
     3566                                    redirectTo: finalRedirect,
    35393567                                    userType: user.user_type || 'user'
    35403568                                }));
    … …  
    35843612                                            (err, boss) => {
    35853613                                                let userType = 'store_employee';
    3586                                                 let redirectTo = 'store-employee.html';
     3614                                                let finalRedirect = redirectTo || 'store-employee.html';
    35873615
    35883616                                                if (boss) {
    35893617                                                    userType = 'store_owner';
    3590                                                     redirectTo = 'store-owner.html';
     3618                                                    finalRedirect = redirectTo || 'store-owner.html';
    35913619                                                }
    35923620
    … …  
    35943622                                                tempAdminSessions.delete(sessionId);
    35953623
    3596                                                 // Create new permanent session
     3624                                                // Create new permanent session with personal_ prefix
    35973625                                                const newSessionId = generateSessionId();
    35983626                                                sessions.set(newSessionId, `personal_${userId}`);
    35993627
    3600                                                 console.log(`Password changed successfully for ${userType} ${userId}, redirecting to ${redirectTo}`);
     3628                                                console.log(`Password changed successfully for ${userType} ${userId}, redirecting to ${finalRedirect}`);
    36013629
    36023630                                                database.logAudit(userId, 'FORCED_PASSWORD_CHANGE', 'auth', userId.toString(),
    36033631                                                    `${userType} forced password change completed`, ipAddress);
    36043632
    3605                                                 // Set the cookie with proper options
     3633                                                // Set the cookie with proper options - extended to 24 hours
    36063634                                                res.writeHead(200, {
    36073635                                                    'Content-Type': 'application/json',
    3608                                                     'Set-Cookie': `sessionId=${newSessionId}; HttpOnly; Path=/; Max-Age=3600; SameSite=Strict`
     3636                                                    'Set-Cookie': `sessionId=${newSessionId}; HttpOnly; Path=/; Max-Age=86400; SameSite=Strict`
    36093637                                                });
     3638
    36103639                                                res.end(JSON.stringify({
    36113640                                                    success: true,
    36123641                                                    message: 'Password changed successfully.',
    3613                                                     redirectTo: redirectTo,
     3642                                                    redirectTo: finalRedirect,
    36143643                                                    userType: userType
    36153644                                                }));
    … …  
    36683697                        body += chunk.toString();
    36693698                    });
    3670 
    36713699                    req.on('end', () => {
    36723700                        const { firstName, lastName, ssn, email, password, storeId, dateOfHire } = JSON.parse(body);
    … …  
    37753803                                                    database.database.run('ROLLBACK');
    37763804                                                    console.error('Error inserting personal:', err);
     3805
    37773806                                                    if (err.code === '23505') {
    37783807                                                        res.writeHead(400, { 'Content-Type': 'application/json' });
    3779                                                         res.end(JSON.stringify({ success: false, message: 'This personal ID is already taken. Please try again.' }));
     3808                                                        res.end(JSON.stringify({
     3809                                                            success: false,
     3810                                                            message: 'This personal ID is already taken. Please try again.'
     3811                                                        }));
    37803812                                                    } else {
    37813813                                                        res.writeHead(400, { 'Content-Type': 'application/json' });
    … …  
    38173849                                                                        }
    38183850
    3819                                                                         database.database.run('COMMIT', (err) => {
    3820                                                                             if (err) {
    3821                                                                                 database.database.run('ROLLBACK');
    3822                                                                                 console.error('Error committing transaction:', err);
    3823                                                                                 res.writeHead(500, { 'Content-Type': 'application/json' });
    3824                                                                                 res.end(JSON.stringify({ success: false, message: 'Error completing registration' }));
    3825                                                                                 return;
     3851                                                                        // Also create entry in users table for login with force_password_change = 1
     3852                                                                        database.database.run(
     3853                                                                            'INSERT INTO users (id, username, email, password, user_type, force_password_change) VALUES (?, ?, ?, ?, ?, ?)',
     3854                                                                            [
     3855                                                                                newPersonalId,
     3856                                                                                `${firstName} ${lastName}`,
     3857                                                                                email,
     3858                                                                                bcrypt.hashSync(password, 10),
     3859                                                                                'store_employee',
     3860                                                                                1
     3861                                                                            ],
     3862                                                                            (err) => {
     3863                                                                                if (err) {
     3864                                                                                    console.error('Error creating user entry for employee:', err);
     3865                                                                                }
     3866
     3867                                                                                database.database.run('COMMIT', (err) => {
     3868                                                                                    if (err) {
     3869                                                                                        database.database.run('ROLLBACK');
     3870                                                                                        console.error('Error committing transaction:', err);
     3871                                                                                        res.writeHead(500, { 'Content-Type': 'application/json' });
     3872                                                                                        res.end(JSON.stringify({ success: false, message: 'Error completing registration' }));
     3873                                                                                        return;
     3874                                                                                    }
     3875
     3876                                                                                    database.logAudit(personalId, 'EMPLOYEE_REGISTERED', 'employee', newPersonalId, `Employee registered: ${firstName} ${lastName}`, ipAddress);
     3877
     3878                                                                                    res.writeHead(200, { 'Content-Type': 'application/json' });
     3879                                                                                    res.end(JSON.stringify({
     3880                                                                                        success: true,
     3881                                                                                        message: 'Employee registered successfully!',
     3882                                                                                        employeeId: newPersonalId,
     3883                                                                                        name: `${firstName} ${lastName}`
     3884                                                                                    }));
     3885                                                                                });
    38263886                                                                            }
    3827 
    3828                                                                             database.logAudit(personalId, 'EMPLOYEE_REGISTERED', 'employee', newPersonalId, `Employee registered: ${firstName} ${lastName}`, ipAddress);
    3829 
    3830                                                                             res.writeHead(200, { 'Content-Type': 'application/json' });
    3831                                                                             res.end(JSON.stringify({
    3832                                                                                 success: true,
    3833                                                                                 message: 'Employee registered successfully!',
    3834                                                                                 employeeId: newPersonalId,
    3835                                                                                 name: `${firstName} ${lastName}`
    3836                                                                             }));
    3837                                                                         });
     3887                                                                        );
    38383888                                                                    }
    38393889                                                                );
    … …  
    38873937                        body += chunk.toString();
    38883938                    });
    3889 
    38903939                    req.on('end', () => {
    38913940                        const { employeeId, storeId } = JSON.parse(body);
    … …  
    39754024                                                                                    }
    39764025
    3977                                                                                     database.database.run('COMMIT', (commitErr) => {
    3978                                                                                         if (commitErr) {
    3979                                                                                             database.database.run('ROLLBACK');
    3980                                                                                             console.error('Error committing transaction:', commitErr);
    3981                                                                                             res.writeHead(500, { 'Content-Type': 'application/json' });
    3982                                                                                             res.end(JSON.stringify({ success: false, message: 'Error completing deletion' }));
    3983                                                                                             return;
     4026                                                                                    // Also delete from users table
     4027                                                                                    database.database.run(
     4028                                                                                        'DELETE FROM users WHERE id = ?',
     4029                                                                                        [employeeId],
     4030                                                                                        (err) => {
     4031                                                                                            if (err) {
     4032                                                                                                console.error('Error deleting from users:', err);
     4033                                                                                            }
     4034
     4035                                                                                            database.database.run('COMMIT', (commitErr) => {
     4036                                                                                                if (commitErr) {
     4037                                                                                                    database.database.run('ROLLBACK');
     4038                                                                                                    console.error('Error committing transaction:', commitErr);
     4039                                                                                                    res.writeHead(500, { 'Content-Type': 'application/json' });
     4040                                                                                                    res.end(JSON.stringify({ success: false, message: 'Error completing deletion' }));
     4041                                                                                                    return;
     4042                                                                                                }
     4043
     4044                                                                                                database.logAudit(personalId, 'EMPLOYEE_DELETED', 'employee', employeeId, `Employee deleted from store ${storeId}`, ipAddress);
     4045
     4046                                                                                                res.writeHead(200, { 'Content-Type': 'application/json' });
     4047                                                                                                res.end(JSON.stringify({
     4048                                                                                                    success: true,
     4049                                                                                                    message: 'Employee deleted successfully'
     4050                                                                                                }));
     4051                                                                                            });
    39844052                                                                                        }
    3985 
    3986                                                                                         database.logAudit(personalId, 'EMPLOYEE_DELETED', 'employee', employeeId, `Employee deleted from store ${storeId}`, ipAddress);
    3987 
    3988                                                                                         res.writeHead(200, { 'Content-Type': 'application/json' });
    3989                                                                                         res.end(JSON.stringify({
    3990                                                                                             success: true,
    3991                                                                                             message: 'Employee deleted successfully'
    3992                                                                                         }));
    3993                                                                                     });
     4053                                                                                    );
    39944054                                                                                }
    39954055                                                                            );
    … …  
    40464106                        body += chunk.toString();
    40474107                    });
    4048 
    40494108                    req.on('end', () => {
    40504109                        const { employeeId, storeId, status } = JSON.parse(body);
    … …  
    41534212                        body += chunk.toString();
    41544213                    });
    4155 
    41564214                    req.on('end', () => {
    41574215                        const { employeeId, storeId, firstName, lastName, email } = JSON.parse(body);
    … …  
    42234281                                                    res.end(JSON.stringify({ success: false, message: 'Error updating employee information' }));
    42244282                                                    return;
     4283                                                }
     4284
     4285                                                // Also update in users table if email was changed
     4286                                                if (email) {
     4287                                                    database.database.run(
     4288                                                        'UPDATE users SET email = ? WHERE id = ?',
     4289                                                        [email, employeeId],
     4290                                                        (err) => {
     4291                                                            if (err) {
     4292                                                                console.error('Error updating user email:', err);
     4293                                                            }
     4294                                                        }
     4295                                                    );
     4296                                                }
     4297
     4298                                                if (firstName || lastName) {
     4299                                                    database.database.get(
     4300                                                        'SELECT first_name, last_name FROM personal WHERE id = ?',
     4301                                                        [employeeId],
     4302                                                        (err, personal) => {
     4303                                                            if (!err && personal) {
     4304                                                                const newUsername = `${personal.first_name} ${personal.last_name}`;
     4305                                                                database.database.run(
     4306                                                                    'UPDATE users SET username = ? WHERE id = ?',
     4307                                                                    [newUsername, employeeId],
     4308                                                                    (err) => {
     4309                                                                        if (err) {
     4310                                                                            console.error('Error updating user username:', err);
     4311                                                                        }
     4312                                                                    }
     4313                                                                );
     4314                                                            }
     4315                                                        }
     4316                                                    );
    42254317                                                }
    42264318
    … …  
    45824674                body += chunk.toString();
    45834675            });
    4584 
    45854676            req.on('end', () => {
    45864677                const { productCode, storeId } = JSON.parse(body);
    … …  
    46524743                body += chunk.toString();
    46534744            });
    4654 
    46554745            req.on('end', () => {
    46564746                const { storeId, period, startDate, endDate, type } = JSON.parse(body);
Note: See TracChangeset for help on using the changeset viewer.