Changeset 79fff4f for interfejs


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

Location:
interfejs
Files:
5 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    }
Note: See TracChangeset for help on using the changeset viewer.