Skip to main content

Updating Profile

This guide covers how to view your profile information and update the fields you're permitted to change.


Overview

What is Your Profile?

Your profile contains your personal and employment information:

  1. Personal Information - Name, email, phone, address
  2. Employment Details - Start date, contract type, hours
  3. Role Information - Job role and permissions
  4. Company Details - Your company assignment

What You Can Edit

Staff members can edit limited fields to maintain data integrity:

CategoryEditableRead-Only
PersonalPhone, AddressName, Email, Date of Birth
EmploymentNoneStart Date, End Date, Contract Hours
RoleNoneRole Name, Permissions
CompanyNoneCompany Name
Why Limited Editing?

Employment and role information is managed by your Company Manager to ensure payroll accuracy and compliance with HR policies. Contact your manager to request changes to read-only fields.


Viewing Your Profile

Accessing Profile

  1. Navigate to My Profile in Staff Portal
  2. Or click your name in the navigation header
  3. Profile details are displayed

Profile API

Endpoint: GET /api/staff/profile

// Source: src/app/api/staff/profile/route.ts:22-119
// Fetch your profile data
const getProfile = async () => {
const response = await fetch('/api/staff/profile')
const { data } = await response.json()
return data.profile
}

Profile Data Structure

// Profile response structure
interface ProfileData {
// Identity
id: string
companyId: string
email: string
firstName: string
lastName: string
fullName: string

// Contact
phone: string | null
address: string | null

// Employment
dateOfBirth: string | null
employmentStartDate: string | null
employmentEndDate: string | null
employmentType: string | null
contractHours: number | null
hourlyRate: number | null

// Status
isActive: boolean
roleId: string | null
roleName: string | null
roleColor: string | null
notes: string | null

// Relations
company: {
id: string
name: string
industry_template_id: string
}
role: {
id: string
name: string
description: string
color: string
permissions: object
}

// Edit permissions
canEdit: {
personalInfo: boolean // Phone and address only
emergency: boolean // Not available
preferences: boolean // Not available
avatar: boolean // Not available
bio: boolean // Not available
employment: boolean // Read-only
company: boolean // Read-only
}
}

Profile Sections

Personal Information

FieldDescriptionEditable
Full NameFirst and last name❌ Read-only
EmailLogin email address❌ Read-only
PhoneContact phone number✅ Editable
AddressHome address✅ Editable
Date of BirthYour birth date❌ Read-only

Employment Details

FieldDescriptionFormat
Start DateEmployment commencementDD/MM/YYYY
End DateEmployment end (if applicable)DD/MM/YYYY
Employment TypeFull-time, part-time, casualText
Contract HoursWeekly contracted hoursNumber
Hourly RatePay rate (if hourly)£XX.XX

Role Information

FieldDescription
Role NameYour assigned job role
Role DescriptionWhat the role entails
Role ColourVisual identifier on schedules
PermissionsWhat you can access

Company Information

FieldDescription
Company NameYour employer
IndustryBusiness type

Updating Your Profile

Editable Fields

You can update:

FieldValidationExample
PhoneValid format+44 7700 900000
AddressFree text123 High Street, London

Update API

Endpoint: PATCH /api/staff/profile

// Source: src/app/api/staff/profile/route.ts:125-254
// Update your profile
const updateProfile = async (updates: ProfileUpdate) => {
const response = await fetch('/api/staff/profile', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updates)
})

return response.json()
}

// Example usage
await updateProfile({
phone: '+44 7700 900123',
address: '456 New Street, Manchester, M1 1AA'
})

Allowed Fields

// Source: src/app/api/staff/profile/route.ts:154-158
// Only these fields can be updated by staff
const allowedFields = {
phone: body.phone,
address: body.address
}

Update Response

// Successful update response
{
success: true,
data: {
profile: {
id: "staff-uuid",
firstName: "John",
lastName: "Smith",
phone: "+44 7700 900123",
address: "456 New Street, Manchester, M1 1AA",
// ... all profile fields
}
}
}

Phone Number

Format Guidelines

FormatExampleStatus
UK Mobile07700 900123✅ Valid
UK Mobile (+44)+44 7700 900123✅ Valid
UK Landline020 7946 0958✅ Valid
International+1 555 123 4567✅ Valid

Phone Validation

// Phone number validation
const isValidPhone = (phone: string): boolean => {
// Remove spaces and special characters for validation
const cleaned = phone.replace(/[\s\-\(\)]/g, '')

// Check for valid patterns
const patterns = [
/^(\+44|0)7\d{9}$/, // UK mobile
/^(\+44|0)\d{10}$/, // UK landline
/^\+\d{10,15}$/ // International
]

return patterns.some(p => p.test(cleaned))
}

Update Phone Example

// Update phone number
const updatePhone = async (newPhone: string) => {
const response = await fetch('/api/staff/profile', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
phone: newPhone
})
})

if (!response.ok) {
const error = await response.json()
throw new Error(error.message)
}

return response.json()
}

Address

Address Format

Provide a complete postal address:

Line 1: Street address
Line 2: Additional info (optional)
City: City or town
Postcode: UK postcode

Example Addresses

// Single-line address
"123 High Street, London, SW1A 1AA"

// Multi-line address
"Flat 4B, Wellington House
15 Market Square
Manchester
M1 2AB"

Update Address Example

// Update address
const updateAddress = async (newAddress: string) => {
const response = await fetch('/api/staff/profile', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
address: newAddress
})
})

return response.json()
}

// Usage
await updateAddress('456 New Road, Birmingham, B1 1BB')

Profile Display Component

Profile View

// Profile display component
const ProfileView = ({ profile }: { profile: ProfileData }) => (
<div className="card-glass p-6 space-y-6">
{/* Header */}
<div className="flex items-center gap-4">
<div className="w-16 h-16 rounded-full bg-coral-gradient flex items-center justify-center text-white text-xl font-bold">
{profile.firstName[0]}{profile.lastName[0]}
</div>
<div>
<h2 className="text-xl font-semibold">{profile.fullName}</h2>
<p className="text-secondary-text">{profile.roleName}</p>
</div>
</div>

{/* Contact Section */}
<Section title="Contact Information">
<Field label="Email" value={profile.email} readonly />
<Field label="Phone" value={profile.phone} editable />
<Field label="Address" value={profile.address} editable />
</Section>

{/* Employment Section */}
<Section title="Employment Details">
<Field label="Start Date" value={formatDate(profile.employmentStartDate)} readonly />
<Field label="Contract Type" value={profile.employmentType} readonly />
<Field label="Contract Hours" value={`${profile.contractHours}h/week`} readonly />
</Section>

{/* Company Section */}
<Section title="Company">
<Field label="Company" value={profile.company.name} readonly />
<Field label="Role" value={profile.roleName} readonly />
</Section>
</div>
)

Edit Form

// Profile edit form
const ProfileEditForm = ({ profile, onSave }) => {
const [phone, setPhone] = useState(profile.phone || '')
const [address, setAddress] = useState(profile.address || '')
const [saving, setSaving] = useState(false)

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setSaving(true)

try {
await onSave({ phone, address })
// Show success message
} catch (error) {
// Show error message
} finally {
setSaving(false)
}
}

return (
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label className="block text-sm font-medium mb-1">Phone Number</label>
<input
type="tel"
value={phone}
onChange={(e) => setPhone(e.target.value)}
className="form-input w-full"
placeholder="+44 7700 900123"
/>
</div>

<div>
<label className="block text-sm font-medium mb-1">Address</label>
<textarea
value={address}
onChange={(e) => setAddress(e.target.value)}
className="form-input w-full"
rows={3}
placeholder="Enter your full address"
/>
</div>

<button
type="submit"
disabled={saving}
className="form-button w-full"
>
{saving ? 'Saving...' : 'Save Changes'}
</button>
</form>
)
}

Validation

Phone Validation

// Source: src/lib/validation/staff.schemas.ts (similar pattern)
const phoneSchema = z.string()
.optional()
.refine(
(val) => !val || /^[\+\d\s\-\(\)]{10,20}$/.test(val),
'Invalid phone number format'
)

Address Validation

// Address validation
const addressSchema = z.string()
.optional()
.max(500, 'Address too long (max 500 characters)')

Validation Errors

ErrorCauseSolution
Invalid phone formatIncorrect number formatUse valid UK or international format
Address too longExceeds 500 charactersShorten address
Validation failedMultiple issuesCheck all field formats

Read-Only Information

Requesting Changes

For read-only fields, contact your Company Manager:

Change RequiredWho to ContactMethod
Name correctionCompany ManagerEmail or in person
Email changeCompany ManagerFormal request
Role changeCompany ManagerHR process
Contract hoursCompany ManagerContract amendment
Employment datesCompany ManagerHR records

Why Fields Are Read-Only

FieldReason
NameLegal documents, payroll
EmailAuthentication, communications
Employment DatesEntitlements calculation
Contract HoursPayroll, scheduling
RolePermissions, access control

Best Practices

Keeping Information Current

  1. Update Phone - Keep contact number current
  2. Update Address - Ensure postal address is correct
  3. Report Errors - Notify manager of incorrect data
  4. Review Regularly - Check profile quarterly

Privacy Considerations

DataVisibility
Your EmailCompany Manager, System Admin
Your PhoneCompany Manager only
Your AddressCompany Manager only
Your RoleAll company staff

Troubleshooting

Common Issues

IssueCauseSolution
Cannot save changesNetwork errorRetry, check connection
Phone rejectedInvalid formatUse valid format
Address too longExceeds limitShorten address
Profile not loadingSession expiredRe-login

Error Messages

ErrorMeaningAction
Authentication requiredSession expiredLogin again
Validation failedInvalid dataCheck field formats
Staff record not foundAccount issueContact manager
ForbiddenAccount inactiveContact manager

Mobile View

Responsive Profile

On mobile devices:

// Mobile profile display
const MobileProfile = ({ profile }) => (
<div className="p-4 space-y-4">
{/* Avatar and name */}
<div className="text-center">
<div className="w-20 h-20 mx-auto rounded-full bg-coral-gradient flex items-center justify-center text-white text-2xl font-bold">
{profile.firstName[0]}{profile.lastName[0]}
</div>
<h2 className="mt-2 text-lg font-semibold">{profile.fullName}</h2>
<p className="text-secondary-text">{profile.roleName}</p>
</div>

{/* Contact details */}
<div className="space-y-3">
<MobileField icon={Mail} label="Email" value={profile.email} />
<MobileField icon={Phone} label="Phone" value={profile.phone} editable />
<MobileField icon={MapPin} label="Address" value={profile.address} editable />
</div>
</div>
)


Source Files:

  • src/app/api/staff/profile/route.ts - Profile API endpoint
  • src/lib/validation/staff.schemas.ts - Validation schemas
  • src/types/database.types.ts - Staff type definitions
  • src/lib/utils/email.ts - Email normalisation utilities