Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions src/app/admin/ai-setup/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useRouter } from 'next/navigation';
import React, { useState } from 'react';

import { AdminPageLayout } from '@/components/layout/admin-layout';
import VerificationGuard from '@/components/VerificationGuard';

import AndroidInstantSetup from './components/Android/InstantSetup';
import AndroidManualSetup from './components/Android/ManualSetup';
Expand Down Expand Up @@ -153,16 +154,18 @@ export default function AISetupPage() {

return (
<AdminPageLayout title="AI Setup" padding="normal" background="solid">
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
height: '100%',
}}
>
{stepComponents[step]}
</Box>
<VerificationGuard>
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
height: '100%',
}}
>
{stepComponents[step]}
</Box>
</VerificationGuard>
</AdminPageLayout>
);
}
7 changes: 7 additions & 0 deletions src/app/admin/billing/components/BillingSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useEffect, useState } from 'react';

import CancelConfirmModal from '@/components/ui/CancelConfirmModal';
import { useGetPlansQuery } from '@/features/public/publicApiSlice';
import { useVerificationCheck } from '@/features/settings/hooks/useVerificationCheck';
import {
useChangePlan,
useCreateSubscription,
Expand Down Expand Up @@ -71,6 +72,7 @@ export default function BillingSection() {
const { downgrade } = useDowngradeToFree();
const { subscription, isSubscribed, isCancelled, currentPlanId } =
useSubscription();
const { blockOperationWithAlert } = useVerificationCheck();

const tierOrder = { FREE: 0, BASIC: 1, PRO: 2 };
const sortedPlans = [...plans].sort(
Expand Down Expand Up @@ -108,6 +110,11 @@ export default function BillingSection() {
tier: 'FREE' | 'BASIC' | 'PRO',
planId: string,
): Promise<void> => {
// Check verification before any plan operations with detailed message
if (!blockOperationWithAlert('switch plans')) {
return;
}

if (label.startsWith('Go with')) {
if (!subscription || subscription.status === 'cancelled') {
await create(planId);
Expand Down
9 changes: 9 additions & 0 deletions src/app/admin/booking/components/TaskManager/BookingModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ import { type Service } from '@/features/service/serviceApi';
import { useCreateServiceBookingMutation } from '@/features/service/serviceBookingApi';
import type { ServiceManagement } from '@/features/service-management/serviceManagementApi';
import { useGetServiceFormFieldsQuery } from '@/features/service-management/serviceManagementApi';
import { useVerificationCheck } from '@/features/settings/hooks/useVerificationCheck';
import { useAppSelector } from '@/redux/hooks';
import type { RootState } from '@/redux/store';
interface Props {
onClose: () => void;
onCreate: (service: Service) => void;
Expand Down Expand Up @@ -296,7 +298,9 @@ const BookingModal: React.FC<Props> = ({
Record<string, string>
>({});
const [createServiceBooking] = useCreateServiceBookingMutation();

const user = useAppSelector(state => state.auth.user);
const { blockOperationWithAlert } = useVerificationCheck();

// Get custom form fields for the selected service
const { data: customFormFields = [] } = useGetServiceFormFieldsQuery(
Expand Down Expand Up @@ -445,6 +449,11 @@ const BookingModal: React.FC<Props> = ({

const handleCreate = async (): Promise<void> => {
try {
// Check verification before creating booking
if (!blockOperationWithAlert('create bookings')) {
return;
}

if (!user) {
throw new Error('User is missing, please login again.');
}
Expand Down
146 changes: 146 additions & 0 deletions src/app/admin/overview/components/VerificationReminder.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
'use client';

import {
Alert,
AlertTitle,
Box,
Button,
Chip,
Typography,
} from '@mui/material';
import { useRouter } from 'next/navigation';
import React from 'react';

import { useGetVerificationQuery } from '@/features/settings/settingsApi';

interface VerificationReminderProps {
userId: string;
}

export default function VerificationReminder({
userId,
}: VerificationReminderProps) {
const router = useRouter();
const { data: verificationData, isLoading } = useGetVerificationQuery(
userId,
{
skip: !userId,
},
);

if (isLoading || !verificationData) {
return null;
}

// Check if both email and phone are verified
const isFullyVerified =
verificationData.emailVerified && verificationData.mobileVerified;

if (isFullyVerified) {
return null; // Don't show reminder if fully verified
}

const handleGoToSettings = () => {
router.push('/admin/settings');
};

const unverifiedCount = [
!verificationData.emailVerified,
!verificationData.mobileVerified,
].filter(Boolean).length;

return (
<Box sx={{ mb: 3 }}>
<Alert
severity="error"
sx={{
borderRadius: 2,
border: '2px solid #f44336',
backgroundColor: '#ffebee',
'& .MuiAlert-message': {
width: '100%',
},
}}
>
<AlertTitle sx={{ color: '#d32f2f', fontWeight: 'bold' }}>
🚨 Account Verification Required - {unverifiedCount} Item
{unverifiedCount > 1 ? 's' : ''} Pending
</AlertTitle>

<Typography variant="body1" sx={{ mb: 2, fontWeight: 500 }}>
<strong>Important:</strong> Your account requires verification to
access all features and ensure security.
<br />
<strong>Impact:</strong> Some operations are currently blocked until
verification is complete.
</Typography>

<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5, mb: 3 }}>
{!verificationData.emailVerified && (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<Chip
label="UNVERIFIED"
color="error"
size="small"
sx={{ fontWeight: 'bold' }}
/>
<Typography variant="body2" color="text.secondary">
Email: {verificationData.email ?? 'Not provided'}
</Typography>
</Box>
)}
{!verificationData.mobileVerified && (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<Chip
label="UNVERIFIED"
color="error"
size="small"
sx={{ fontWeight: 'bold' }}
/>
<Typography variant="body2" color="text.secondary">
Phone: {verificationData.mobile ?? 'Not provided'}
</Typography>
</Box>
)}
</Box>

<Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap' }}>
<Button
variant="contained"
size="medium"
onClick={handleGoToSettings}
sx={{
backgroundColor: '#d32f2f',
color: 'white',
fontWeight: 'bold',
px: 3,
'&:hover': {
backgroundColor: '#b71c1c',
},
}}
>
Complete Verification Now
</Button>

<Button
variant="outlined"
size="medium"
onClick={() => window.open('/admin/settings', '_blank')}
sx={{
borderColor: '#d32f2f',
color: '#d32f2f',
fontWeight: 'bold',
px: 3,
'&:hover': {
borderColor: '#b71c1c',
backgroundColor: '#ffebee',
},
}}
>
Open Settings in New Tab
</Button>
</Box>
</Alert>
</Box>
);
}
7 changes: 7 additions & 0 deletions src/app/admin/overview/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import React, { useEffect } from 'react';
import { AdminPageLayout } from '@/components/layout/admin-layout';
import ProFeatureModal from '@/components/ui/ProFeatureModal';
import { useSubscription } from '@/features/subscription/useSubscription';
import { useAppSelector } from '@/redux/hooks';
import { getPlanTier, isFreeOrBasicPlan, isProPlan } from '@/utils/planUtils';

import ActivitySection from './components/ActivitySection';
import CampaignProgressSection from './components/CompaignProgressSection';
import RecentService from './components/RecentService';
import VerificationReminder from './components/VerificationReminder';

const styles = {
contentContainer: {
Expand All @@ -36,6 +38,8 @@ const styles = {
};

export default function OverviewPage() {
const user = useAppSelector(state => state.auth.user);

const { subscription } = useSubscription();
const params = useSearchParams();
const router = useRouter();
Expand Down Expand Up @@ -66,6 +70,9 @@ export default function OverviewPage() {
return (
<>
<AdminPageLayout title="Overview" padding="normal" background="solid">
{/* Verification Reminder */}
{user?._id && <VerificationReminder userId={user._id} />}

<Box sx={styles.contentContainer}>
<ActivitySection />
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ import {
useSaveServiceFormFieldsMutation,
useUpdateServiceMutation,
} from '@/features/service-management/serviceManagementApi';
import { useVerificationCheck } from '@/features/settings/hooks/useVerificationCheck';
import { useAppSelector } from '@/redux/hooks';
import type { RootState } from '@/redux/store';
import theme from '@/theme';

import CustomFormModal from './CustomFormModal';
Expand Down Expand Up @@ -219,6 +221,7 @@ export default function EditServiceModal({

useMediaQuery(theme.breakpoints.down('sm'));
useMediaQuery(theme.breakpoints.down('xs'));

const user = useAppSelector(state => state.auth.user);

// Fallback: try to get user from auth check if Redux state is empty
Expand All @@ -232,6 +235,7 @@ export default function EditServiceModal({
const [createService, { isLoading: isCreating }] = useCreateServiceMutation();
const [updateService, { isLoading: isUpdating }] = useUpdateServiceMutation();
const [saveServiceFormFields] = useSaveServiceFormFieldsMutation();
const { blockOperationWithAlert } = useVerificationCheck();

// 获取现有的表单字段
const { data: existingFormFields = [] } = useGetServiceFormFieldsQuery(
Expand Down Expand Up @@ -309,6 +313,11 @@ export default function EditServiceModal({

const handleSubmit = async (): Promise<void> => {
try {
// Check verification before creating/updating service
if (!blockOperationWithAlert('manage services')) {
return;
}

// Validation before submission
if (!formData.name.trim()) {
alert('Please enter a service name');
Expand Down
11 changes: 7 additions & 4 deletions src/app/admin/service-management/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';

import { AdminPageLayout } from '@/components/layout/admin-layout';
import VerificationGuard from '@/components/VerificationGuard';
import { useSubscription } from '@/features/subscription/useSubscription';
import { getPlanTier, isProPlan } from '@/utils/planUtils';

Expand Down Expand Up @@ -71,10 +72,12 @@ export default function ServiceManagementPage() {
padding="normal"
background="solid"
>
<ServiceManagementContent
isCreateModalOpen={isCreateModalOpen}
onCloseCreateModal={handleCloseCreateModal}
/>
<VerificationGuard>
<ServiceManagementContent
isCreateModalOpen={isCreateModalOpen}
onCloseCreateModal={handleCloseCreateModal}
/>
</VerificationGuard>
</AdminPageLayout>
);
}
2 changes: 1 addition & 1 deletion src/app/admin/settings/SettingsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ const SettingsContainer = styled(Box)({
export default function SettingsSection() {
return (
<SettingsContainer>
<VerificationSection />
<GreetingSection />
<UserProfileSection />
<VerificationSection />
<IntegrationsSection />
<CompanyInfoSection />
<BillingAddressSection />
Expand Down
Loading