- Add comprehensive Company Wiki feature with complete state management - CompanyWikiManager, empty states, invite modals - Implement new Chat system with enhanced layout and components - ChatLayout, ChatSidebar, MessageThread, FileUploadInput - Create modern Login and OTP verification flows - LoginNew page, OTPVerification component - Add new Employee Forms system with enhanced controller - Introduce Figma-based design components and multiple choice inputs - Add new font assets (NeueMontreal) and robot images for onboarding - Enhance existing components with improved styling and functionality - Update build configuration and dependencies - Remove deprecated ModernLogin component
279 lines
15 KiB
TypeScript
279 lines
15 KiB
TypeScript
import React from 'react';
|
|
|
|
interface FigmaQuestionProps {
|
|
questionNumber?: string | number;
|
|
title: string;
|
|
description?: string;
|
|
answer?: string;
|
|
onAnswerChange?: (value: string) => void;
|
|
onBack?: () => void;
|
|
onNext?: () => void;
|
|
showNavigation?: boolean;
|
|
nextLabel?: string;
|
|
backLabel?: string;
|
|
className?: string;
|
|
}
|
|
|
|
export const FigmaQuestion: React.FC<FigmaQuestionProps> = ({
|
|
questionNumber = 'Q',
|
|
title,
|
|
description,
|
|
answer = '',
|
|
onAnswerChange,
|
|
onBack,
|
|
onNext,
|
|
showNavigation = true,
|
|
nextLabel = 'Next',
|
|
backLabel = 'Back',
|
|
className = ''
|
|
}) => {
|
|
return (
|
|
<div className={`w-[600px] px-5 pt-5 pb-6 bg-Other-White rounded-2xl outline outline-1 outline-offset-[-1px] outline-Neutrals-NeutralSlate200 inline-flex flex-col justify-end items-end gap-4 ${className}`}>
|
|
{/* Question Header */}
|
|
<div className="self-stretch inline-flex justify-start items-start gap-3">
|
|
<div className="justify-start text-zinc-300 text-xl font-medium font-['Inter'] leading-loose">
|
|
{questionNumber}
|
|
</div>
|
|
<div className="flex-1 inline-flex flex-col justify-start items-start gap-2">
|
|
<div className="self-stretch justify-start text-Neutrals-NeutralSlate950 text-xl font-semibold font-['Inter'] leading-loose">
|
|
{title}
|
|
</div>
|
|
{description && (
|
|
<div className="self-stretch justify-start text-Neutrals-NeutralSlate500 text-sm font-normal font-['Inter'] leading-tight">
|
|
{description}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Separator */}
|
|
<div data-svg-wrapper>
|
|
<svg width="563" height="5" viewBox="0 0 563 5" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<g filter="url(#filter0_d_37_3168)">
|
|
<path d="M1.5 1L561.5 1" stroke="var(--Neutrals-NeutralSlate200, #E9EAEB)" />
|
|
</g>
|
|
<defs>
|
|
<filter id="filter0_d_37_3168" x="0" y="0.5" width="563" height="4" filterUnits="userSpaceOnUse" colorInterpolationFilters="sRGB">
|
|
<feFlood floodOpacity="0" result="BackgroundImageFix" />
|
|
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
|
|
<feOffset dy="1.5" />
|
|
<feGaussianBlur stdDeviation="0.75" />
|
|
<feComposite in2="hardAlpha" operator="out" />
|
|
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0" />
|
|
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_37_3168" />
|
|
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_37_3168" result="shape" />
|
|
</filter>
|
|
</defs>
|
|
</svg>
|
|
</div>
|
|
|
|
{/* Answer Section */}
|
|
<div className="self-stretch inline-flex justify-start items-center gap-3">
|
|
<div className="justify-start text-zinc-300 text-xl font-medium font-['Inter'] leading-loose">A</div>
|
|
<div className="flex-1">
|
|
<textarea
|
|
value={answer}
|
|
onChange={(e) => onAnswerChange?.(e.target.value)}
|
|
placeholder="Type your answer...."
|
|
className="w-full bg-transparent outline-none resize-none text-Neutrals-NeutralSlate950 text-base font-normal font-['Inter'] leading-normal placeholder:text-Neutrals-NeutralSlate500 min-h-[100px]"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Navigation */}
|
|
{showNavigation && (
|
|
<div className="inline-flex justify-start items-center gap-3">
|
|
{onBack && (
|
|
<button
|
|
onClick={onBack}
|
|
className="px-4 py-3.5 bg-Neutrals-NeutralSlate100 rounded-[999px] flex justify-center items-center gap-1 overflow-hidden hover:bg-Neutrals-NeutralSlate200 transition-colors"
|
|
>
|
|
<div data-svg-wrapper className="relative">
|
|
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M13 15L8 10L13 5" stroke="var(--Neutrals-NeutralSlate950, #0A0D12)" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
</svg>
|
|
</div>
|
|
<div className="px-1 flex justify-center items-center">
|
|
<div className="justify-center text-Neutrals-NeutralSlate950 text-sm font-medium font-['Inter'] leading-tight">
|
|
{backLabel}
|
|
</div>
|
|
</div>
|
|
</button>
|
|
)}
|
|
|
|
{onNext && (
|
|
<button
|
|
onClick={onNext}
|
|
className="px-4 py-3.5 bg-Brand-Orange rounded-[999px] outline outline-2 outline-offset-[-2px] outline-blue-400 flex justify-center items-center gap-1 overflow-hidden hover:bg-orange-600 transition-colors"
|
|
>
|
|
<div className="px-1 flex justify-center items-center">
|
|
<div className="justify-center text-Other-White text-sm font-medium font-['Inter'] leading-tight">
|
|
{nextLabel}
|
|
</div>
|
|
</div>
|
|
<div data-svg-wrapper className="relative">
|
|
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M8 15L13 10L8 5" stroke="var(--Neutrals-NeutralSlate0, #FDFDFD)" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
</svg>
|
|
</div>
|
|
</button>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
|
|
// Progress Bar Component
|
|
export const FigmaProgressBar: React.FC<{ currentStep: number; totalSteps: number }> = ({ currentStep, totalSteps }) => {
|
|
return (
|
|
<div className="p-4 bg-Neutrals-NeutralSlate100 rounded-[50px] inline-flex justify-center items-center gap-2 overflow-hidden">
|
|
{Array.from({ length: totalSteps }, (_, index) => {
|
|
const isActive = index < currentStep;
|
|
const isFirst = index === 0;
|
|
return (
|
|
<div key={index}>
|
|
<svg width={isFirst ? "24" : "4"} height="4" viewBox={`0 0 ${isFirst ? "24" : "4"} 4`} fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<rect width={isFirst ? "24" : "4"} height="4" rx="2" fill={isActive ? "var(--Brand-Orange, #5E48FC)" : "var(--Neutrals-NeutralSlate300, #D5D7DA)"} />
|
|
</svg>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
// Rating Scale Component (1-10)
|
|
export const FigmaRatingScale: React.FC<{
|
|
question: string;
|
|
leftLabel: string;
|
|
rightLabel: string;
|
|
value?: number;
|
|
onChange: (value: number) => void;
|
|
scale?: number;
|
|
}> = ({ question, leftLabel, rightLabel, value, onChange, scale = 10 }) => {
|
|
return (
|
|
<div className="w-[1440px] h-[810px] py-6 relative bg-Neutrals-NeutralSlate0 inline-flex flex-col justify-center items-center gap-9">
|
|
<div className="w-full max-w-[464px] min-w-[464px] flex flex-col justify-center items-center gap-12">
|
|
<div className="flex flex-col justify-center items-center gap-8">
|
|
<div className="self-stretch text-center justify-start text-Neutrals-NeutralSlate950 text-2xl font-medium font-['Neue_Montreal'] leading-normal">{question}</div>
|
|
<div className="inline-flex justify-center items-center gap-3">
|
|
<div className="justify-center text-Neutrals-NeutralSlate950 text-sm font-medium font-['Inter'] leading-tight">{leftLabel}</div>
|
|
{Array.from({ length: scale }, (_, index) => {
|
|
const number = index + 1;
|
|
const isSelected = value === number;
|
|
return (
|
|
<div
|
|
key={number}
|
|
onClick={() => onChange(number)}
|
|
className={`w-12 h-12 relative rounded-[576.35px] overflow-hidden cursor-pointer transition-colors ${isSelected ? 'bg-Brand-Orange' : 'bg-Neutrals-NeutralSlate100 hover:bg-Neutrals-NeutralSlate200'
|
|
}`}
|
|
>
|
|
<div className={`absolute inset-0 flex items-center justify-center text-xl font-medium font-['Inter'] leading-7 ${isSelected ? 'text-white' : 'text-Neutrals-NeutralSlate950'
|
|
}`}>
|
|
{number}
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
<div className="justify-center text-Neutrals-NeutralSlate950 text-sm font-medium font-['Inter'] leading-tight">{rightLabel}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
// Text Area Component
|
|
export const FigmaTextArea: React.FC<{
|
|
question: string;
|
|
value?: string;
|
|
onChange: (value: string) => void;
|
|
placeholder?: string;
|
|
}> = ({ question, value, onChange, placeholder = "Type your answer...." }) => {
|
|
return (
|
|
<div className="w-[1440px] h-[810px] py-6 relative bg-Neutrals-NeutralSlate0 inline-flex flex-col justify-center items-center gap-9">
|
|
<div className="w-full max-w-[464px] min-w-[464px] flex flex-col justify-start items-start gap-12">
|
|
<div className="self-stretch flex flex-col justify-start items-start gap-8">
|
|
<div className="self-stretch text-center justify-start text-Neutrals-NeutralSlate950 text-2xl font-medium font-['Neue_Montreal'] leading-normal">{question}</div>
|
|
<div className="self-stretch min-h-40 p-5 relative bg-Neutrals-NeutralSlate100 rounded-xl inline-flex justify-start items-start gap-2.5">
|
|
<textarea
|
|
value={value}
|
|
onChange={(e) => onChange(e.target.value)}
|
|
className="flex-1 bg-transparent text-Neutrals-NeutralSlate950 text-base font-normal font-['Inter'] leading-normal placeholder:text-Neutrals-NeutralSlate500 outline-none resize-none"
|
|
placeholder={placeholder}
|
|
rows={6}
|
|
/>
|
|
<div className="w-3 h-3 absolute right-5 bottom-5">
|
|
<div className="w-2 h-2 absolute top-0.5 left-0.5 outline outline-1 outline-offset-[-0.50px] outline-Neutrals-NeutralSlate500" />
|
|
<div className="w-1 h-1 absolute bottom-0 right-0 outline outline-1 outline-offset-[-0.50px] outline-Neutrals-NeutralSlate500" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
// Navigation Buttons Component
|
|
export const FigmaNavigationButtons: React.FC<{
|
|
onBack?: () => void;
|
|
onNext: () => void;
|
|
onSkip?: () => void;
|
|
nextDisabled?: boolean;
|
|
currentStep?: number;
|
|
totalSteps?: number;
|
|
}> = ({ onBack, onNext, onSkip, nextDisabled = false, currentStep, totalSteps }) => {
|
|
return (
|
|
<>
|
|
{/* Progress indicator */}
|
|
{currentStep && totalSteps && (
|
|
<div className="px-3 py-1.5 left-[24px] top-[24px] absolute bg-Neutrals-NeutralSlate100 rounded-[50px] inline-flex justify-center items-center gap-2 overflow-hidden">
|
|
<div className="justify-start text-Neutrals-NeutralSlate500 text-sm font-medium font-['Inter'] uppercase leading-none">{currentStep} of {totalSteps}</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Skip button */}
|
|
{onSkip && (
|
|
<div
|
|
onClick={onSkip}
|
|
className="px-3 py-1.5 left-[1363px] top-[24px] absolute bg-Neutrals-NeutralSlate100 rounded-[50px] inline-flex justify-center items-center gap-2 overflow-hidden cursor-pointer hover:bg-Neutrals-NeutralSlate200"
|
|
>
|
|
<div className="justify-start text-Neutrals-NeutralSlate500 text-sm font-medium font-['Inter'] leading-none">Skip</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Progress bar */}
|
|
{currentStep && totalSteps && (
|
|
<div className="w-[464px] max-w-[464px] min-w-[464px] left-[488px] top-[24px] absolute flex flex-col justify-start items-center gap-4">
|
|
<FigmaProgressBar currentStep={currentStep} totalSteps={totalSteps} />
|
|
</div>
|
|
)}
|
|
|
|
{/* Navigation buttons */}
|
|
<div className="self-stretch inline-flex justify-start items-start gap-2">
|
|
{onBack && (
|
|
<button
|
|
onClick={onBack}
|
|
className="h-12 px-8 py-3.5 bg-Neutrals-NeutralSlate100 rounded-[999px] flex justify-center items-center gap-1 overflow-hidden hover:bg-Neutrals-NeutralSlate200"
|
|
>
|
|
<div className="px-1 flex justify-center items-center">
|
|
<div className="justify-center text-Neutrals-NeutralSlate950 text-sm font-medium font-['Inter'] leading-tight">Back</div>
|
|
</div>
|
|
</button>
|
|
)}
|
|
<button
|
|
onClick={onNext}
|
|
disabled={nextDisabled}
|
|
className="flex-1 h-12 px-4 py-3.5 bg-Brand-Orange rounded-[999px] outline outline-2 outline-offset-[-2px] outline-blue-400 flex justify-center items-center gap-1 overflow-hidden disabled:opacity-50 disabled:cursor-not-allowed"
|
|
>
|
|
<div className="px-1 flex justify-center items-center">
|
|
<div className="justify-center text-Other-White text-sm font-medium font-['Inter'] leading-tight">Next</div>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
</>
|
|
);
|
|
};
|