F11: Manage Company Profile Flow - Feature Analysis¶
Overview¶
The Manage Company Profile Flow provides a comprehensive interface for authorized company administrators to manage and maintain their organization’s presence on the Futr Connect platform. This feature is accessible only to users with company-linked roles and offers a structured approach to updating company information, managing digital assets, and controlling who has access to company profile administration. The flow consists of multiple sections including Company Profile, Overview & Positioning, Sources & Social, Company Insights, Engagement Dashboard, and Settings.
Access Control¶
- Owner Role: Full access to all sections including the ability to add/remove team members and unpublish the company page
- Editor Role: Access to content management areas but cannot add/remove team members or unpublish the page
- Permission Enforcement: Role-based access is enforced through Firebase Auth validation
API Endpoints¶
1. Get Company Profile Data¶
GET /api/company/{company_id}/
2. Update Company Profile¶
PATCH /api/company/{company_id}/
3. Get Company People¶
GET /api/people/?company={company_id}
4. Add Company People¶
POST /api/people/
5. Invite People¶
POST /api/company-member-invitation-request
6. Get Company Finance Insights¶
GET /api/finance/?company={company_id}
7. Add Company Finance Insights¶
POST /api/finance/
8. Get Company Metrics¶
GET /api/metric/?company={company_id}
9. Add Company Metrics¶
POST /api/metric/
10. Get Company Content¶
GET /api/content/?company={company_id}
11. Add Company Content¶
POST /api/content/
12. Get Company News¶
GET /api/news/?company={company_id}
13. Add Company News¶
POST /api/news/
14. Get Company Privacy¶
GET /api/company-privacy-policy/?company={company_id}
15. Add Company Privacy¶
POST /api/company-privacy-policy/
16. Get Company Members¶
GET /api/company-member/?company={company_id}
17. Add Company Member¶
POST /api/company-member/
18. Unpublish Company Page¶
POST /api/company-closure/
Key Workflow Sections¶
1. Entry Point¶
- Access Method: Users with company-linked roles access the “Manage Company Page” section through the user interface
- Authentication Required: Only authorized users (Owner or Editor) can access this section
- Access Control: Role-based permissions determine which specific sections and actions are available to the user
- Navigation: Side navigation menu provides access to all company management areas
2. Company Management Navigation¶
- Left Sidebar Menu Contains:
- Company Profile
- Overview & Positioning
- Sources & Social
- Company Insights
- Engagement Dashboard
- Settings
- Navigation Flow:
- Menu items are fixed and consistent across all company management pages
- Active/selected menu item is visually highlighted
- Navigation preserves the user’s position when switching between sections
- Sidebar is designed to be responsive and collapsible on smaller screens
3. Company Profile Tab¶
- Purpose: Manages core company identity information and digital assets
- Fields:
- Company Logo Upload (JPG, PNG, PDF; Max 5MB)
- Name (required)
- Email (required)
- Company Founded Date
- HQ Address
- Zip Code
- State
- Phone Number
- Meeting URL (Calendly) - for integration with “Book Meeting” functionality
- Video Uploads:
- 2 minute intro video
- First Call Video
- Demo Video
- Action Buttons:
- Add Video - Opens modal for video URL input
- Delete - Removes selected video
- Edit - Opens edit mode for selected content
- Save - Persists changes to backend
- Cancel - Discards unsaved changes
- Validation:
- Required fields are enforced
- All uploads are validated for file type and size constraints
- Calendly URL must be in valid format
4. Overview & Positioning Tab¶
- Purpose: Defines the company’s market positioning and value proposition
- Structured Inputs:
- Overview (one-line pitch) - Short, impactful company description
- About (short company description) - Extended overview text
- Best Suited For - Multi-select tags targeting ideal user personas (e.g., Data Scientists, Project Managers)
- Where to Use - Use cases or implementation environments
- Standout Functions - Unique features that differentiate the company
- Market Categories - Tag selection from predefined options (e.g., SaaS, Cybersecurity)
- Data Format:
- Text fields support rich formatting where appropriate
- Tags are selected from predefined lists for consistency
- Multi-select interfaces for categories and personas
- Content Guidelines:
- Overview limited to concise, impactful statement
- About section has character limits for readability
- Tags and categories follow platform taxonomy
5. Sources & Social Tab¶
- Purpose: Manages external company resources and social media links
- Input Fields:
- Website (main company URL)
- Career page
- Event Pages
- Customer Portal
- Social Media Links:
- YouTube
- URL Validation:
- All links must be valid URLs
- Social media links should conform to the respective platform URL patterns
- Action Buttons:
- Submit - Saves all link updates to backend
- Cancel - Discards unsaved changes
- Implementation Notes:
- Links are validated before submission
- URL fields include appropriate placeholders as input guides
- Non-required fields can be left empty
- Invalid URLs are highlighted with appropriate error messages
6. Company Insights Section¶
- Purpose: Enables management of detailed company information across multiple specialized categories
- Entry Point: User accesses Company Insights from the left sidebar menu
- Subsection Navigation:
- People
- Finance
- Metrics
- Implementation Notes:
- Each subsection has its own dedicated interface and functionality
- Data entered in these sections appears on the public Company Detail Page
- Content is organized to facilitate easy discovery of company capabilities
6.1 People Subsection¶
- Entry Point: User navigates to Company Insights → People
- Layout and Form Sections:
- Type Selection Dropdown:
- Executive Leadership
- Primary Investors
- Board Members
- Advisors
- Dynamic Form Fields:
- For Executive Leadership, Board Members, Advisors:
- Profile Picture Upload (JPG, PNG, PDF; max 5MB)
- Name (required)
- Title (required)
- LinkedIn URL (optional)
- For Primary Investors:
- Company Logo Upload (JPG, PNG, PDF; max 5MB)
- Investor/Company Name (required)
- Action Buttons:
- Add People – Creates additional entries for the selected type
- Save – Commits changes to backend
- Cancel – Discards unsaved changes
- Validation and Behavior:
- Form dynamically adapts based on selected type
- Required field validation varies by type
- File uploads validated for type and size
- Multiple entries supported via Add More functionality
- Entries displayed grouped by type
- API Endpoints:
- Add Person
- Update Person
- Delete Person
- Upload Profile Image
- Get Person Types Metadata
6.2 Finance Subsection¶
- Entry Point: User navigates to Company Insights → Finance
- Layout and Form Sections:
- IPO Status:
- Radio options: Private, Public, Other
- Conditional field: Yahoo Finance Link (appears when “Public” is selected)
- Latest Funding Round:
- Dropdown with predefined options (Pre-seed, Seed, Series A-F, Self-funded/Angel, Other)
- Latest Valuation:
- Optional numeric input for company valuation (USD)
- Annual Revenue:
- Dropdown with predefined ranges:
- Less than $1M
- $1M–$10M
- $10M–$50M
- $50M–$100M
- $100M–$250M
- $250M–$500M
- $500M–$1B
- $1B–$10B
- $10B+
- Total Funding:
- Optional numeric input for total funding amount (USD)
- Action Buttons:
- Save – Submits finance data
- Cancel – Resets form or exits without saving
- Validation and Behavior:
- IPO Status is required
- Yahoo Finance Link must be valid URL when visible
- Monetary fields support large value inputs
- Backend supports partial updates for flexibility
- API Endpoints:
- Add Finance Info
- Update Finance Info
- Get Finance Metadata (for dropdown options)
6.3 Metrics Subsection¶
- Entry Point: User navigates to Company Insights → Metrics
- Layout and Form Sections:
- Total Employees:
- Dropdown with predefined ranges:
- 0–10
- 10–25
- 25–50
- 50–100
- 100–200
- 200–500
- 500–1000
- 1000–2000
- 2000–5000
- 5000–10000
- 10000+
- Total Customers:
- Dropdown with similar predefined ranges
- Client Retention %:
- Text input (max 7 characters)
- Action Buttons:
- Save – Submits metrics data
- Cancel – Exits without saving
- Validation and Behavior:
- Client Retention field accepts numeric values with optional % symbol
- Clean responsive design adapts to all device sizes
- API Endpoints:
- Add Metrics
- Update Metrics
- Get Metrics Metadata
7. Engagement Dashboard¶
- Entry Point: User accesses Engagement Dashboard from the left sidebar menu
- Dashboard Sections:
- Top Metrics Cards:
- Impression Count
- Follow Count
- Visits
- News Interaction
- Free Trial Clicks
- Content Interactions
- Meetings Booked
- Graphical Insights:
- Meetings vs Free Trial bar chart
- Visits & Interactions by Product area chart
- Time Filter Buttons:
- This Month
- Last Month
- This Year
- Last 12 Months
- Custom Date Range
- Functional Features:
- Auto-refreshing data based on selected time filter
- Dynamic graph updates
- Responsive layout (grid on desktop, stacked on mobile)
- Tooltip details on hover
- Data Sources:
- Profile interactions
- Product engagement
- Content views
- Meeting bookings
- Free trial clicks
- API Endpoints:
- Get Engagement Metrics
- Time Filter Parameters
- Graph Data
- Calendly Click Tracking
- Free Trial Click Tracking
8. Settings Section¶
8.1 Profile Management¶
- Entry Point: User navigates to Settings → Profile Management
- Layout and Display:
- Add Users Section:
- Input field for Email ID or User ID
- Add and Cancel buttons
- Access Control Table:
- S.No
- User Name
- User Email
- Joining Date
- Role
- Action (Remove link, only visible to Owner)
- Add Manager Permissions:
- Editors can access:
- Company Profile
- Overview & Positioning
- Sources & Social
- Company Insights (all subsections)
- Engagement Dashboard
- Functional Notes:
- Email/User ID validation on add
- Duplicate entry prevention
- Only Owner can remove users or add managers
- API Endpoints:
- Add Manager
- Remove Manager
- Get Access Control List
- Permission Check Middleware
8.2 Subscription purchase¶
- Entry Point: User navigates to Settings → Subscription Page
- Layout and Display:
- Explore plane button
- Redirect to price section
- Price section page:
- show subscription cards
- Functional Notes:
- User can buy subscriptions
- Permissions:
- Only Owner can buy subscriptions
8.3 Unpublish Section¶
- Entry Point: User navigates to Settings → Unpublish Page
- Layout and Display:
- Single Unpublish Page button
- Modal dialog for confirmation
- Modal – Unpublish Confirmation:
- Title: “Why are you unpublishing this page?”
- Subtext explaining republishing option
- Radio Options:
- Company no longer active
- Updating page content
- Created by mistake
- Other reason (with text field)
- Unpublish Page and Cancel buttons
- Functional Notes:
- Unpublishing hides profile from public view
- Unpublished pages no longer appear in search/listings
- Warning about potential deletion after inactivity
- Permissions:
- Only Owner role can access/use this section
- API Endpoints:
- Unpublish Company Page
- Get Unpublish Reason Metadata
- Submit Unpublish Reason
- Republish Company Page (planned)
Stage Management¶
Recent Changes and Updates¶
-
UI Enhancements:
- Added tooltip for company names longer than 10 characters
- Fixed Calendly modal close issue -
Preview Functionality:
- Added local state for company preview while updating company details
- Implemented preview synchronization across tabs -
State Model Updates:
const Address = types.model('Address', { address_1: types.maybeNull(types.string), address_2: types.maybeNull(types.string), postal_code: types.maybeNull(types.string), state: types.maybeNull(types.string) }); const Category = types.model('Category', { value: types.string, label: types.string }); const SocialLink = types.model('Social-links', { career: types.maybeNull(types.string), customer_portal: types.maybeNull(types.string), event_page: types.maybeNull(types.string), facebook: types.maybeNull(types.string), instagram: types.maybeNull(types.string), linkedin: types.maybeNull(types.string), twitter: types.maybeNull(types.string), website: types.maybeNull(types.string), youtube: types.maybeNull(types.string) }); export const CompanyDetails = types.model('Company-details', { id: types.identifier, logo: types.maybeNull(types.frozen()), name: types.maybeNull(types.string), email: types.maybeNull(types.string), company_founded: types.maybeNull(types.string), company_addresses: types.maybeNull(Address), phone_number: types.maybeNull(types.string), meeting_url: types.maybeNull(types.string), short_video: types.frozen(), demo_video: types.frozen(), first_call: types.frozen(), overview: types.maybeNull(types.string), about: types.maybeNull(types.string), best_suited_for: types.array(types.string), where_to_use: types.maybeNull(types.string), standout_function: types.maybeNull(types.string), category: types.array(Category), company_social_links: types.maybeNull(SocialLink) }); export const ManageCompanyStore = types .model({ previewCompany: types.maybeNull(ManageCompanySchema.CompanyDetails) }) .extend(withEnvironment) .actions((self) => ({ updateCompanyPreview: ({ key, value, id }: { key: string; value: any; id: string }) => { if (!!self.previewCompany) { // @ts-ignore: Index signature for dynamic update self.previewCompany[key] = value; self.previewCompany.id = id; } else { self.previewCompany = cast(ManageCompanySchema.CompanyDetails.create({ id: id })); if (self.previewCompany) { self.previewCompany[key] = value; } } }, clearUpdateCompany: () => { self.previewCompany = null; }, setPreviewCompanyValue: (value) => { self.previewCompany = cast(ManageCompanySchema.CompanyDetails.create(value)); } })); -
Mobile Navigation Enhancement:
- When users click a nav item with child items on mobile, the first child page now opens automatically
State Definitions¶
Local State Types¶
type CompanyStatus = 'unpublished' | 'draft' | 'published' | null;
type Option = { label: string; value: string };
// Form Types
### Form Types
type companyProfileFormSchemaType = yup.InferType<typeof companyProfileFormSchema>;
type overviewPositionSchemaType = yup.InferType<typeof overviewPositionSchema>;
type sourceAndSocialSchemaType = yup.InferType<typeof sourceAndSocialSchema>;
React Query Types¶
type CompanyDetailsQuery = {
data: CompanyDetails | undefined;
isError: boolean;
error: CustomErrorType | undefined;
isLoading: boolean;
refetch: () => void;
};
type UpdateCompanyInfoMutation = {
mutateAsync: (args: { companyId: string; body: FormData }) => Promise<CustomSuccessType>;
isPending: boolean;
};
type UpdateCompanyAddressMutation = {
mutateAsync: (args: { addressId: string; body: UpdateCompanyAddressBody }) => Promise<CustomSuccessType>;
isPending: boolean;
};
type CreateCompanyAddressMutation = {
mutateAsync: (args: { body: Required<UpdateCompanyAddressBody> & { company: string } }) => Promise<CustomSuccessType>;
isPending: boolean;
};
``````typescript
type UpdateCompanyOverViewMutation = {
mutateAsync: (args: { companyId: string; body: Record<string, any> }) => Promise<CustomSuccessType>;
isPending: boolean;
};
type UpdateCompanySocialLinkMutation = {
mutateAsync: (args: { companyId: string; body: Record<string, string> }) => Promise<CustomSuccessType>;
isPending: boolean;
};
type RemoveFirstCallOrDemoVideoMutation = {
mutateAsync: (args: { companyId: string; body: Record<string, null | string> }) => Promise<CustomSuccessType>;
};
MobX-State-Tree Models¶
ManageCompanyStore={
manageCompanyOwner, // types.map(ManageCompanySchema.User)
manageCompanyRole, // types.map(ManageCompanySchema.UserRole)
manageCompanyNavigation // types.maybeNull(ManageCompanySchema.ManageCompanyNavigation)
updateManageCompanyNavigation(value),
addMangeCompanyRole(value),
addManageCompanyOwner(value),
removeFirstCallOrDemoVideo({ companyId, body }),
updateCompanyInfo({ companyId, body }),
updateCompanyAddress({ addressId, body }),
createCompanyAddress({ body }),
updateCompanyPosition({ companyId, body }),
updateCompanySocialLinks({ companyId, body }),
closeCompany(body),
addManagerToCompany(body),
removeManager(userId),
addPrivacyPolicy(body),
deletePrivacyPolicy({ policyId, isAddPresent }),
createFinanceInsights(body),
updateFinanceInsights({ id, body }),
createMetricsInsights(body),
updateMetricsInsights({ id, body }),
sendInvitation(body)
}
Database Models¶
PostgreSQL Models¶
Company¶
id(UUID, primary key)name(varchar, required)logo(ImageField, nullable)overview(text, nullable)short_video(URLField, nullable)category(ManyToManyField to CompanyCategory)is_featured_by_admin(boolean, default: false)is_claimed(boolean, default: false)claimed_by(ForeignKey to User, nullable)meeting_url(URLField, nullable)social_link(OneToOneField to CompanySocialLink)
People¶
id(UUID, primary key)company(ForeignKey to Company)designation_type(ForeignKey to DesignationType)avatar(ImageField, nullable)name(varchar, required)title(varchar, nullable)url(URLField, nullable)
Finance¶
id(UUID, primary key)company(ForeignKey to Company)ipo_status(varchar, required)latest_funding_round(varchar, required)yahoo_finance_url(URLField, nullable)latest_valuation(varchar, nullable)annual_revenue(varchar, required)total_funding(varchar, nullable)
Metric¶
id(UUID, primary key)company(ForeignKey to Company)total_employees(varchar, required)total_customers(varchar, required)client_retention(IntegerField, nullable)
Content¶
id(UUID, primary key)company(ForeignKey to Company)link(URLField, required)title(varchar, required)video_type(varchar, required)marked_video_as(varchar, choices: demo_video, featured_video, video_call, nullable)total_count(PositiveIntegerField, default: 0)
News¶
id(UUID, primary key)company(ForeignKey to Company)source_url(URLField, nullable)total_count(PositiveIntegerField, default: 0)
CompanyPrivacyPolicy¶
id(UUID, primary key)company(OneToOneField to Company)file(FileField, nullable)privacy_url(URLField, nullable)
CompanyMember¶
id(UUID, primary key)company(ForeignKey to Company)user(ForeignKey to User)role(varchar, choices: manager, viewer, default: viewer)invited_by(ForeignKey to User, nullable)
CompanyClosure¶
id(UUID, primary key)company(ForeignKey to Company)reason(ForeignKey to ClosureReason)description(text, nullable)
Validations and Business Logic¶
Form Validations¶
- Company Profile Form
- Logo: Accept only JPG, PNG, PDF; Max 5MB
- Name: Required, max 100 chars
- Email: Required, valid email format
- Phone Number: Optional, must match E.164 format
- Meeting URL: Optional, valid URL, must contain “calendly.com”
- Video Form
- URL: Required, valid URL, must be YouTube or Vimeo embed URL
- Title: Required, max 100 chars
- Type: Required, must be one of: intro, first_call, demo, other
- Positioning Form
- Overview: Max 150 chars
- About: Max 2000 chars
- Best Suited For: Max 10 tags
- Market Categories: Must be selected from predefined list
- Links Form
- All URLs must be valid URL format
- Social media links must match the respective platform’s URL pattern
Access Control Logic¶
- Role-Based Permissions
- Owner:
- Full read/write access to all company data
- Can add/remove managers
- Can unpublish the company page
- Editor:
- Read/write access to content sections
- No access to Profile Management section
- No access to Unpublish Page section
- Permission Enforcement
- Server-side: Django permissions based on Firebase custom claims
- Client-side: React components conditionally render based on user role
- API endpoints validate permissions before processing requests
- Multi-User Conflict Prevention
- Optimistic locking mechanism using “updated_at” timestamps
- Last writer wins strategy with user warnings for concurrent edits
- Real-time notifications of changes made by other team members
Third-Party Integrations¶
Calendly Integration¶
- Implementation Details
- Meeting URL field in Company Profile accepts Calendly URLs
- When a valid Calendly URL is provided, a “Book Meeting” button appears on the company’s public profile
- Implementation uses direct linking to Calendly scheduling page
- Validation Rules
- URL must start with “https://calendly.com/“
- URL should be for a valid Calendly user/event
- URL is displayed as-is without modification
Firebase Authentication¶
- Role Management
- Claims are set when a user is added as an Owner or Editor
- Backend validates claims before allowing access to protected endpoints
- Permission Flow
- Backend middleware extracts company ID and role from token
- API endpoints check if user has appropriate role for requested company
YouTube/Vimeo Integration¶
- Video Embedding
- Content section supports embedding videos from YouTube and Vimeo
- URLs are validated to ensure they match YouTube or Vimeo embed formats
- iframes are sanitized to prevent security issues
- Video Preview
- Thumbnails are automatically fetched from video providers
- Video metadata (duration, publication date) is displayed when available
- Embed code is generated automatically based on the platform
User Experience Considerations¶
- Progressive Disclosure
- Form sections are organized from basic (Company Profile) to advanced (Settings)
- Complex functionality (e.g., Company Insights) is accessible via subsections
- Help text and tooltips provide contextual guidance
- Responsive Design
- Management interface adapts to desktop, tablet, and mobile viewports
- Form inputs resize appropriately for touch interfaces
- Error Handling
- Inline validation with clear error messages
- Form submission validates all fields before API calls
- Network errors are presented with retry options
- Unsaved changes warnings when navigating away
- Accessibility
- Form labels are properly associated with inputs
- ARIA attributes for dynamic content
- Keyboard navigation support
- Color contrast meets WCAG AA standards
- Performance Optimization
- Lazy loading of complex form sections
- Image optimization before upload
- Pagination for large data sets (e.g., product listings)
- Debounced search inputs
Implementation Notes¶
- Technical Requirements
- Frontend: Nextjs with MobX-State-Tree and React query for state management
- Backend: Django REST Framework with PostgreSQL
- Authentication: JWT Token auth
- Storage: Cloud Storage for uploaded files
- Analytics: Google Analytics for tracking engagement metrics
- Development Priorities
- Core functionality (Profile, Overview, Links) implemented first
- Company Insights sections prioritized by user value
- Settings implemented last to ensure core functions are stable
- Testing Strategy
- Unit tests for validation logic
- Integration tests for API endpoints
- E2E tests for critical flows (adding company, managing permissions)
- User testing for form usability
- Security Considerations
- File uploads validated and sanitized
- Role-based access strictly enforced
- Input validation prevents XSS
- Rate limiting on API endpoints
- Audit logging for sensitive operations (adding/removing users)
Preview Functionality¶
Overview¶
The Preview functionality allows users to see real-time changes to their company page without making permanent API calls. This feature improves the user experience by providing immediate visual feedback while maintaining data integrity.
Implementation Details¶
1. Tab Switching Behavior¶
interface TabSwitchingBehavior {
// Save changes when switching tabs
onTabSwitch: {
saveCurrentTab: () => Promise<void>; // Makes API call to save current tab data
loadNewTab: () => Promise<void>; // Fetches data for new tab
validateBeforeSwitch: () => boolean; // Checks for required fields
};
// Track unsaved changes
changeTracking: {
hasUnsavedChanges: boolean;
lastSavedState: Record<string, any>;
currentState: Record<string, any>;
};
}
2. Preview State Management¶
interface PreviewState {
// Local storage management
storage: {
key: string; // Unique key for company preview data
getTempState: () => Record<string, any>;
setTempState: (data: Record<string, any>) => void;
clearTempState: () => void;
};
// Preview data structure
previewData: {
currentTab: string;
unsavedChanges: Record<string, any>;
timestamp: number;
};
}
Preview Implementation¶
-
Local Storage Management
const PreviewStorageManager = { setPreviewData: (companyId: string, tabName: string, data: any) => { const key = `company_preview_${companyId}`; const existingData = localStorage.getItem(key); const previewData = existingData ? JSON.parse(existingData) : {}; previewData[tabName] = { data, timestamp: Date.now() }; localStorage.setItem(key, JSON.stringify(previewData)); }, getPreviewData: (companyId: string, tabName: string) => { const key = `company_preview_${companyId}`; const previewData = localStorage.getItem(key); return previewData ? JSON.parse(previewData)[tabName] : null; }, clearPreviewData: (companyId: string) => { const key = `company_preview_${companyId}`; localStorage.removeItem(key); } }; -
Preview Component Integration
interface PreviewManager { // Preview mode toggle isPreviewMode: boolean; togglePreviewMode: () => void; // Data management getPreviewData: () => CompanyData; updatePreviewData: (tabName: string, data: any) => void; // Synchronization syncWithAPI: () => Promise<void>; revertToSaved: () => void; } // Implementation const usePreviewManager = (companyId: string) => { const [isPreviewMode, setIsPreviewMode] = useState(false); // Update preview when form changes const updatePreview = useCallback((tabName: string, data: any) => { PreviewStorageManager.setPreviewData(companyId, tabName, data); }, [companyId]); // Get combined preview data const getPreviewData = useCallback(() => { const tabs = ['profile', 'overview', 'social', 'insights']; return tabs.reduce((acc, tab) => { const tabData = PreviewStorageManager.getPreviewData(companyId, tab); return { ...acc, [tab]: tabData?.data }; }, {}); }, [companyId]); return { isPreviewMode, togglePreviewMode: () => setIsPreviewMode(prev => !prev), updatePreview, getPreviewData }; }; -
Form Integration
const CompanyTabForm = ({ tabName, initialData }) => { const { isPreviewMode, updatePreview } = usePreviewManager(companyId); // Handle form changes const handleChange = (values) => { if (isPreviewMode) { updatePreview(tabName, values); } }; return ( <Form initialValues={initialData} onChange={handleChange} // ... other form props > {/* Form fields */} </Form> ); };
Preview Features¶
-
Real-time Updates
- Changes in any tab are immediately reflected in preview
- No API calls made until explicit save
- Preview state persists across page refreshes -
Tab Synchronization
- Each tab maintains its own preview state
- Changes in one tab don’t affect others
- Preview shows combined state of all tabs -
Data Persistence
- Preview data stored in localStorage
- Automatic cleanup after successful save
- Expiry mechanism for stale preview data -
User Interface
- Preview mode toggle button
- Visual indicators for unsaved changes
- Option to revert to last saved state
Preview Security Considerations¶
-
Data Storage
interface PreviewSecurity { // Data encryption encryption: { encryptPreviewData: (data: any) => string; decryptPreviewData: (encrypted: string) => any; }; // Data validation validation: { validatePreviewData: (data: any) => boolean; sanitizePreviewData: (data: any) => any; }; } -
Access Control
- Preview data accessible only to authorized users
- Separate preview storage per company
- Automatic cleanup of expired preview data
[Rest of the original content follows…]
State Management¶
[Previous content continues…]