Add staff permission controls for editing staff and customers

- Add can_edit_staff and can_edit_customers dangerous permissions
- Move Site Builder, Services, Locations, Time Blocks, Payments to Settings permissions
- Link Edit Others' Schedules and Edit Own Schedule permissions
- Add permission checks to StaffViewSet (partial_update, toggle_active, verify_email)
- Add permission checks to CustomerViewSet (update, partial_update, verify_email)
- Fix CustomerViewSet permission key mismatch (can_access_customers)
- Hide Edit/Verify buttons on Staff and Customers pages without permission
- Make dangerous permissions section more visually distinct (darker red)
- Fix StaffDashboard links to use correct paths (/dashboard/my-schedule)
- Disable settings sub-permissions when Access Settings is unchecked

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
poduck
2025-12-29 17:38:48 -05:00
parent d7700a68fd
commit 47657e7076
105 changed files with 29709 additions and 873 deletions

View File

@@ -0,0 +1,34 @@
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import HelpAutomations from '../HelpAutomations';
vi.mock('react-i18next', () => ({
useTranslation: () => ({
t: (key: string, fallback?: string) => fallback || key,
}),
}));
const renderWithRouter = (component: React.ReactElement) => {
return render(
React.createElement(MemoryRouter, {}, component)
);
};
describe('HelpAutomations', () => {
it('renders the page title', () => {
renderWithRouter(React.createElement(HelpAutomations));
expect(screen.getByText('Automations Guide')).toBeInTheDocument();
});
it('renders back button', () => {
renderWithRouter(React.createElement(HelpAutomations));
expect(screen.getByText('Back')).toBeInTheDocument();
});
it('renders overview section', () => {
renderWithRouter(React.createElement(HelpAutomations));
expect(screen.getByText('Overview')).toBeInTheDocument();
});
});