feat(account-setup): enhance localization and UI for account setup process

- Added new language support and improved translations for account setup steps across multiple languages.
- Updated the organization step to streamline user input and enhance suggestions for organization names.
- Refactored task management components to improve user experience when adding and managing tasks.
- Removed outdated CSS for admin center components to simplify styling and improve maintainability.
- Introduced new UI elements and transitions for a more engaging account setup experience.
- Enhanced Redux state management to accommodate new features and localization updates.
This commit is contained in:
chamikaJ
2025-07-25 12:50:19 +05:30
parent b688f8e114
commit 7dc3dedda5
22 changed files with 1003 additions and 1073 deletions

View File

@@ -1,3 +1,5 @@
/* Account Setup Page Styles */
/* Steps styling - using Ant Design theme tokens */
.ant-steps-item-finish .ant-steps-item-icon {
border-color: var(--ant-color-primary) !important;
@@ -23,12 +25,17 @@
opacity: 0.6;
}
.ant-steps-item-process .ant-steps-item-icon {
border-color: var(--ant-color-primary) !important;
background-color: var(--ant-color-primary) !important;
color: var(--ant-color-white) !important;
}
.progress-steps .ant-steps-item.ant-steps-item-process .ant-steps-item-title::after {
background-color: var(--ant-color-primary) !important;
width: 60px !important;
}
/* Steps title styling */
.ant-steps-item-title {
color: var(--ant-color-text) !important;
}
@@ -37,7 +44,7 @@
color: var(--ant-color-text-secondary) !important;
}
/* Responsive design improvements */
/* Responsive layout */
@media (max-width: 1000px) {
.progress-steps,
.step,
@@ -72,295 +79,7 @@
}
}
@media (max-width: 1000px) {
.organization-name-form,
.first-project-form,
.create-first-task-form {
width: 90% !important;
max-width: 500px !important;
}
}
@media (max-width: 768px) {
.organization-name-form,
.first-project-form,
.create-first-task-form {
width: 95% !important;
max-width: 400px !important;
}
}
@media (max-width: 500px) {
.organization-name-form,
.first-project-form,
.create-first-task-form {
width: 100% !important;
max-width: 300px !important;
}
}
.vert-text {
max-width: 40px;
background-color: var(--ant-color-bg-container);
color: var(--ant-color-text);
position: relative;
z-index: 99;
margin: 2rem auto;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
padding: 0.5rem;
}
.vert-line {
position: absolute;
left: 0;
right: 0;
width: 100%;
height: 1px;
background-color: var(--ant-color-border);
top: 50%;
transform: translateY(-50%);
}
/* Legacy dark mode classes for backward compatibility */
.dark-mode .vert-text,
.vert-text-dark {
background-color: var(--ant-color-bg-container);
color: var(--ant-color-text);
}
.dark-mode .vert-line,
.vert-line-dark {
background-color: var(--ant-color-border);
}
/* Button and component improvements */
.custom-close-button:hover {
background-color: transparent !important;
}
.setup-action-buttons {
width: 100%;
display: flex;
flex-direction: column;
gap: 1rem;
}
.setup-action-buttons .ant-btn {
min-height: 40px;
font-weight: 500;
}
/* Form styling with Ant Design theme tokens */
.step-form .ant-form-item-label > label {
color: var(--ant-color-text) !important;
}
.step-form .ant-input,
.step-form .ant-input-affix-wrapper {
background-color: var(--ant-color-bg-container) !important;
border-color: var(--ant-color-border) !important;
color: var(--ant-color-text) !important;
}
.step-form .ant-input:focus,
.step-form .ant-input-affix-wrapper:focus,
.step-form .ant-input-affix-wrapper-focused {
background-color: var(--ant-color-bg-container) !important;
border-color: var(--ant-color-primary) !important;
color: var(--ant-color-text) !important;
}
.step-form .ant-input::placeholder {
color: var(--ant-color-text-placeholder) !important;
}
/* Select styling */
.step-form .ant-select-selector {
background-color: var(--ant-color-bg-container) !important;
border-color: var(--ant-color-border) !important;
color: var(--ant-color-text) !important;
}
.step-form .ant-select-selection-placeholder {
color: var(--ant-color-text-placeholder) !important;
}
/* Typography */
.step-form .ant-typography {
color: var(--ant-color-text);
}
.step-form .ant-typography.ant-typography-secondary {
color: var(--ant-color-text-secondary);
}
/* Card styling */
.step-form .ant-card {
background-color: var(--ant-color-bg-container);
border-color: var(--ant-color-border);
}
.step-form .ant-card-body {
color: var(--ant-color-text);
}
/* Checkbox and Radio styling */
.step-form .ant-checkbox-wrapper {
color: var(--ant-color-text);
}
.step-form .ant-radio-wrapper {
color: var(--ant-color-text);
}
/* Smooth transitions for theme switching */
* {
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
}
/* Survey step transitions */
.survey-page-transition {
animation: fadeInUp 0.4s ease-out;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Survey option hover effects */
.survey-option-card {
transition: all 0.2s ease;
}
.survey-option-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
/* Progress bar animation */
.ant-progress-line {
transition: all 0.5s ease-out;
}
/* Survey button animations */
.survey-nav-button {
transition: all 0.2s ease;
}
.survey-nav-button:active {
transform: scale(0.98);
}
/* Project step enhancements */
.project-suggestion-button {
transition: all 0.2s ease;
cursor: pointer;
}
.project-suggestion-button:hover {
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.project-suggestion-button:active {
transform: translateY(0);
}
.template-preview-card {
transition: all 0.3s ease;
cursor: pointer;
}
.template-preview-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}
.template-preview-card.selected {
box-shadow: 0 4px 20px rgba(24, 144, 255, 0.2);
}
/* Enhanced form styling for project step */
.project-step .ant-input-affix-wrapper {
transition: all 0.3s ease;
}
.project-step .ant-input-affix-wrapper:focus-within {
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);
}
.project-step .ant-card {
transition: all 0.3s ease;
}
.project-step .ant-card:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}
/* Organization step enhancements */
.organization-step .ant-input-affix-wrapper {
transition: all 0.3s ease;
}
.organization-step .ant-input-affix-wrapper:focus-within {
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);
border-color: #1890ff;
}
.organization-step .ant-card {
transition: all 0.3s ease;
}
.organization-step .ant-card:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}
.organization-suggestion-button {
transition: all 0.2s ease;
cursor: pointer;
}
.organization-suggestion-button:hover {
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.organization-suggestion-button:active {
transform: translateY(0);
}
/* Character counter styling */
.organization-step .character-counter {
font-size: 12px;
opacity: 0.7;
transition: opacity 0.3s ease;
}
.organization-step .character-counter.active {
opacity: 1;
}
/* Naming tips hover effect */
.organization-step .naming-tip {
transition: all 0.2s ease;
padding: 8px;
}
.organization-step .naming-tip:hover {
background-color: rgba(24, 144, 255, 0.05);
}
/* Tasks step enhancements */
/* Tasks step specific styles */
.tasks-step .task-item-card {
transition: all 0.3s ease;
}
@@ -377,47 +96,70 @@
box-shadow: none !important;
}
.task-suggestion-button {
transition: all 0.2s ease;
cursor: pointer;
}
.task-suggestion-button:hover {
transform: translateY(-1px);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}
.task-suggestion-button:active {
transform: translateY(0);
}
/* Members step enhancements */
.members-step .member-item-card {
/* Project step specific styles */
.project-step .ant-input-affix-wrapper {
transition: all 0.3s ease;
}
.members-step .member-item-card:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
.project-step .ant-input-affix-wrapper:focus-within {
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);
}
.members-step .member-input {
font-size: 16px;
}
.members-step .member-input:focus {
box-shadow: none !important;
}
.email-suggestion-button {
.project-suggestion-button {
transition: all 0.2s ease;
cursor: pointer;
}
.email-suggestion-button:hover {
.project-suggestion-button:hover {
transform: translateY(-1px);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.email-suggestion-button:active {
.project-suggestion-button:active {
transform: translateY(0);
}
/* Organization step specific styles */
.organization-step .ant-input-affix-wrapper {
transition: all 0.3s ease;
}
.organization-step .ant-input-affix-wrapper:focus-within {
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);
border-color: #1890ff;
}
.organization-suggestion-button {
transition: all 0.2s ease;
cursor: pointer;
}
.organization-suggestion-button:hover {
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.organization-suggestion-button:active {
transform: translateY(0);
}
/* Survey step animations */
.survey-page-transition {
animation: fadeInUp 0.4s ease-out;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Theme transitions */
* {
transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
}

View File

@@ -3,7 +3,7 @@ import { useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { Space, Steps, Button, Typography, theme, Dropdown, MenuProps } from '@/shared/antd-imports';
import { GlobalOutlined } from '@/shared/antd-imports';
import { GlobalOutlined, MoonOutlined, SunOutlined } from '@/shared/antd-imports';
import logger from '@/utils/errorLogger';
import { setCurrentStep, setSurveySubStep } from '@/features/account-setup/account-setup.slice';
@@ -33,9 +33,11 @@ import { useAppDispatch } from '@/hooks/useAppDispatch';
import './account-setup.css';
import { IAccountSetupRequest } from '@/types/project-templates/project-templates.types';
import { profileSettingsApiService } from '@/api/settings/profile/profile-settings.api.service';
import { projectTemplatesApiService } from '@/api/project-templates/project-templates.api.service';
import { surveyApiService } from '@/api/survey/survey.api.service';
import { ISurveySubmissionRequest, ISurveyAnswer } from '@/types/account-setup/survey.types';
import { setLanguage } from '@/features/i18n/localesSlice';
import { toggleTheme } from '@/features/theme/themeSlice';
const { Title } = Typography;
@@ -211,6 +213,47 @@ const AccountSetup: React.FC = () => {
}
};
const completeAccountSetupWithTemplate = async () => {
try {
await saveSurveyData(); // Save survey data first
const model: IAccountSetupRequest = {
team_name: sanitizeInput(organizationName),
project_name: null, // No project name when using template
template_id: templateId,
tasks: [],
team_members: [],
survey_data: {
organization_type: surveyData.organization_type,
user_role: surveyData.user_role,
main_use_cases: surveyData.main_use_cases,
previous_tools: surveyData.previous_tools,
how_heard_about: surveyData.how_heard_about,
},
};
const res = await projectTemplatesApiService.setupAccount(model);
if (res.done && res.body.id) {
trackMixpanelEvent(evt_account_setup_complete);
// Refresh user session to update setup_completed status
try {
const authResponse = await dispatch(verifyAuthentication()).unwrap() as IAuthorizeResponse;
if (authResponse?.authenticated && authResponse?.user) {
setSession(authResponse.user);
dispatch(setUser(authResponse.user));
}
} catch (error) {
logger.error('Failed to refresh user session after template setup completion', error);
}
navigate(`/worklenz/projects/${res.body.id}?tab=tasks-list&pinned_tab=tasks-list`);
}
} catch (error) {
logger.error('completeAccountSetupWithTemplate', error);
}
};
const steps = [
{
title: '',
@@ -389,6 +432,15 @@ const AccountSetup: React.FC = () => {
dispatch(setCurrentStep(currentStep + 1));
dispatch(setSurveySubStep(0)); // Reset for next time
}
} else if (currentStep === 2) {
// Project step - check if template is selected
if (templateId) {
// Template selected, complete account setup with template
await completeAccountSetupWithTemplate();
} else {
// No template, proceed to tasks step
dispatch(setCurrentStep(currentStep + 1));
}
} else if (currentStep === 4) {
// Complete setup after members step
completeAccountSetup();
@@ -412,6 +464,10 @@ const AccountSetup: React.FC = () => {
i18n.changeLanguage(languageKey);
};
const handleThemeToggle = () => {
dispatch(toggleTheme());
};
const languageMenuItems: MenuProps['items'] = languages.map(lang => ({
key: lang.key,
label: (
@@ -427,11 +483,23 @@ const AccountSetup: React.FC = () => {
return (
<div
className="min-h-screen w-full flex flex-col items-center py-8 px-4 relative"
className="account-setup-container min-h-screen w-full flex flex-col items-center py-8 px-4 relative"
style={{ backgroundColor: token.colorBgLayout }}
>
{/* Language Switcher - Top Right */}
<div className="absolute top-6 right-6">
{/* Controls - Top Right */}
<div className="absolute top-6 right-6 flex items-center space-x-3">
{/* Theme Switcher */}
<Button
type="text"
size="small"
icon={isDarkMode ? <SunOutlined /> : <MoonOutlined />}
onClick={handleThemeToggle}
className="flex items-center"
style={{ color: token?.colorTextTertiary }}
title={isDarkMode ? 'Switch to light mode' : 'Switch to dark mode'}
/>
{/* Language Switcher */}
<Dropdown
menu={{ items: languageMenuItems }}
placement="bottomRight"
@@ -534,7 +602,6 @@ const AccountSetup: React.FC = () => {
type="primary"
htmlType="submit"
disabled={isContinueDisabled()}
className="min-h-10 font-medium px-8"
onClick={nextStep}
>
{t('continue')}