Skip to content

Commit

Permalink
implement EmployeeProfile
Browse files Browse the repository at this point in the history
  • Loading branch information
Markusplay committed Jan 7, 2025
1 parent 6e18fe1 commit a26e368
Show file tree
Hide file tree
Showing 11 changed files with 166 additions and 79 deletions.
36 changes: 19 additions & 17 deletions src/app/[locale]/(private)/profile/components/code-of-honor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,17 @@ export function CodeOfHonor() {

const t = useTranslations('private.profile');

const handleClick = async () => {
const handleAcceptCodeOfHonor = async () => {
setLoading(true);
const res = await acceptCodeOfHonor();
if (!res) {
errorToast();
return;
}
setUser(res);
setLoading(false);
setUser(res);
};

if (user?.studentProfile?.codeOfHonorSigned) {
return null;
}

return (
<div className="flex flex-col gap-3">
<Heading6>{t('codeOfHonor.title')}</Heading6>
Expand All @@ -48,17 +44,23 @@ export function CodeOfHonor() {
documentsLink: (chunks) => <Link href="/kpi-documents">{chunks}</Link>,
paragraph: (chunks) => <Paragraph className="m-0 text-lg">{chunks}</Paragraph>,
})}

<Button
className="ml-auto w-fit"
loading={loading}
onClick={handleClick}
size={isMobile ? 'medium' : 'big'}
icon={<Check />}
iconPosition="end"
>
{t('button.agree')}
</Button>
{user?.codeOfHonorSignDate ? (
<div className="flex flex-col gap-1">
<Paragraph>Ви надали згоду, щодо принципів та норм, які наведені в представлених документах.</Paragraph>
<Paragraph className="m-0">{user?.codeOfHonorSignDate}</Paragraph>
</div>
) : (
<Button
className="ml-auto w-fit"
loading={loading}
onClick={handleAcceptCodeOfHonor}
size={isMobile ? 'medium' : 'big'}
icon={<Check />}
iconPosition="end"
>
{t('button.agree')}
</Button>
)}
</div>
);
}
3 changes: 0 additions & 3 deletions src/app/[locale]/(private)/profile/components/contacts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ export function Contacts({ contacts, contactTypes }: Props) {
<div className="flex w-full flex-col gap-3">
<Heading6>{t('contact.title')}</Heading6>
<Separator />

<div className="flex w-full flex-col gap-4">
{contacts.map((contact) => (
<EditableItem
Expand All @@ -73,7 +72,6 @@ export function Contacts({ contacts, contactTypes }: Props) {
<div className="mt-6 flex flex-col gap-3">
<Heading6>{t('contact.add-contact')}</Heading6>
<Separator />

<Form {...form}>
<form className="flex flex-col" onSubmit={form.handleSubmit(handleFormSubmit)}>
<div className="flex flex-col gap-5 md:flex-row">
Expand Down Expand Up @@ -104,7 +102,6 @@ export function Contacts({ contacts, contactTypes }: Props) {
</FormItem>
)}
/>

<FormField
control={form.control}
name="contactValue"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { Paragraph } from '@/components/typography/paragraph';

interface Props {
onSave: (newValue: string) => void;
onDelete: () => void;
value?: string;
label?: string;
onDelete?: () => void;
}

export function EditableItem({ label, value, onSave, onDelete }: Props) {
Expand Down Expand Up @@ -39,8 +39,8 @@ export function EditableItem({ label, value, onSave, onDelete }: Props) {
) : (
<div className="flex justify-between gap-4">
<Paragraph className="m-0 font-medium">{value}</Paragraph>
<PencilBold className="h-6 w-6 cursor-pointer text-basic-blue" onClick={() => setIsEditing(true)} />
<XBold className="h-6 w-6 cursor-pointer text-status-danger-300" onClick={onDelete} />
<PencilBold className="size-6 cursor-pointer text-basic-blue" onClick={() => setIsEditing(true)} />
<XBold className="size-6 cursor-pointer text-status-danger-300" onClick={onDelete} />
</div>
)}
</div>
Expand Down
96 changes: 74 additions & 22 deletions src/app/[locale]/(private)/profile/components/info-block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { Card, CardContent } from '@/components/ui/card';
import { cn } from '@/lib/utils';
import { ProfilePicture } from '@/app/[locale]/(private)/profile-picture';
import { useLocalStorage } from '@/hooks/use-storage';
import { User, USER_CATEGORIES } from '@/types/user';
import { Heading4, Heading6 } from '@/components/typography/headers';
import { useTranslations } from 'next-intl';
import { Separator } from '@/components/ui/separator';
Expand All @@ -16,6 +15,9 @@ import { useState } from 'react';
import { PencilBold } from '@/app/images';
import { useServerErrorToast } from '@/hooks/use-server-error-toast';
import { Paragraph } from '@/components/typography/paragraph';
import { User } from '@/types/user';
import { EMPLOYMENT_TYPE, USER_CATEGORIES } from '@/types/constants';
import React from 'react';

interface Props {
className?: string;
Expand All @@ -32,6 +34,7 @@ export function InfoBlock({ className }: Props) {
const { errorToast } = useServerErrorToast();

const studentProfile = user?.studentProfile;
const employeeProfile = user?.employeeProfile;

const handleSave = async () => {
const res = await updateEnglishFullName(fullNameEn);
Expand All @@ -43,6 +46,40 @@ export function InfoBlock({ className }: Props) {
setUser(res);
};

const studentInfo: { label: string; value?: number | string }[] = [
{
label: t('info.subdivision'),
value: studentProfile?.faculty,
},
{
label: t('info.group'),
value: studentProfile?.studyGroup.name,
},
{
label: t('info.education-form'),
value: studentProfile?.formOfEducation,
},
{
label: t('info.study-year'),
value: studentProfile?.studyYear,
},
{
label: t('info.speciality'),
value: studentProfile?.speciality,
},
];

const employeeInfo: { label: string; value?: number | string }[] = [
{
label: t('info.academic-degree'),
value: employeeProfile?.academicDegree,
},
{
label: t('info.academic-status'),
value: employeeProfile?.academicStatus,
},
];

return (
<Card className={cn(className)}>
<CardContent className="flex flex-col gap-6 space-y-1.5 p-9">
Expand Down Expand Up @@ -79,30 +116,45 @@ export function InfoBlock({ className }: Props) {
</div>

<div className="flex flex-col">
<Heading6>{t('info.title')}</Heading6>
<Heading6>{user?.employeeProfile ? t('info.work-title') : t('info.education-title')}</Heading6>
<Separator className="my-3" />
{studentProfile && (
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-3 md:flex-row md:gap-6">
<Paragraph className="m-0 w-[170px] font-semibold text-neutral-400">{t('info.subdivision')}:</Paragraph>
<Paragraph className="m-0 font-medium">{studentProfile?.faculty}</Paragraph>
</div>
<div className="flex flex-col gap-3 md:flex-row md:gap-6">
<Paragraph className="m-0 w-[170px] font-semibold text-neutral-400">{t('info.group')}:</Paragraph>
<Paragraph className="m-0 font-medium">{studentProfile?.studyGroup?.name}</Paragraph>
</div>
<div className="flex flex-col gap-3 md:flex-row md:gap-6">
<Paragraph className="m-0 w-[170px] font-semibold text-neutral-400">{t('info.study-form')}:</Paragraph>
<Paragraph className="m-0 font-medium">{studentProfile?.formOfEducation}</Paragraph>
</div>
<div className="flex flex-col gap-3 md:flex-row md:gap-6">
<Paragraph className="m-0 w-[170px] font-semibold text-neutral-400">{t('info.course')}:</Paragraph>
<Paragraph className="m-0 font-medium">{studentProfile?.studyYear}</Paragraph>
</div>
<div className="flex flex-col gap-3 md:flex-row md:gap-6">
<Paragraph className="m-0 w-[170px] font-semibold text-neutral-400">{t('info.specialty')}:</Paragraph>
<Paragraph className="m-0 font-medium">{studentProfile?.speciality}</Paragraph>
</div>
{studentInfo.map((item, index) => (
<div key={index} className="flex flex-col gap-3 md:flex-row md:gap-6">
<Paragraph className="m-0 w-[170px] font-semibold text-neutral-400">{item.label}:</Paragraph>
<Paragraph className="m-0 font-medium">{item.value}</Paragraph>
</div>
))}
</div>
)}

{employeeProfile && (
<div className="flex flex-col gap-4">
{employeeInfo.map((item, index) => (
<div key={index} className="flex flex-col gap-3 md:flex-row md:gap-6">
<Paragraph className="m-0 w-[170px] font-semibold text-neutral-400">{item.label}:</Paragraph>
<Paragraph className="m-0 font-medium">{item.value}</Paragraph>
</div>
))}

<Heading6>Перелік посад</Heading6>
{employeeProfile.positions.map((position, index) => (
<React.Fragment key={index}>
<Separator className="" />
<div className="flex flex-col gap-3 md:flex-row md:gap-6">
<Paragraph className="m-0 w-[170px] font-semibold text-neutral-400">Посада:</Paragraph>
<Paragraph className="m-0 font-medium">
{position.name} ({EMPLOYMENT_TYPE[position.employment]})
</Paragraph>
</div>

<div className="flex flex-col gap-3 md:flex-row md:gap-6">
<Paragraph className="m-0 w-[170px] font-semibold text-neutral-400">Підрозділ:</Paragraph>
<Paragraph className="m-0 font-medium">{position.subdivision.name}</Paragraph>
</div>
</React.Fragment>
))}
</div>
)}
</div>
Expand Down
8 changes: 4 additions & 4 deletions src/app/[locale]/(private)/profile/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function Profile({ contacts, contactTypes }: Props) {

const isClient = useIsClient();

const isStudent = !!user?.studentProfile;
const isEmployee = !!user?.employeeProfile;

if (!isClient) {
return null;
Expand All @@ -43,9 +43,9 @@ export function Profile({ contacts, contactTypes }: Props) {
<Card className="h-fit w-full">
<CardContent className="flex flex-col gap-6 space-y-1.5 p-9">
<Contacts contacts={contacts} contactTypes={contactTypes} />
{!isStudent && <IntellectAgreement />}
{!isStudent && <IntellectPublicationInfo />}
{isStudent && <CodeOfHonor />}
{isEmployee && <IntellectAgreement />}
{isEmployee && <IntellectPublicationInfo />}
<CodeOfHonor />
</CardContent>
</Card>
</div>
Expand Down
13 changes: 8 additions & 5 deletions src/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,14 +159,17 @@
"title": "Profile",
"subtitle": "Here you can view your profile, edit contacts, add links to accounts, and set appointment details.",
"info": {
"title": "Information about place of study (work)",
"education-title": "Information about place of study",
"work-title": "Information about place of work",
"subdivision": "Subdivision",
"group": "Group",
"grade-book": "Grade book number",
"study-form": "Form of study",
"course": "Course of study:",
"specialty": "Specialty",
"fullNameEN": "Full name in English"
"education-form": "Form of study",
"study-year": "Study year:",
"speciality": "speciality",
"fullNameEN": "Full name in English",
"academic-degree": "Academic degree",
"academic-status": "Academic title"
},
"contact": {
"title": "Contact",
Expand Down
13 changes: 8 additions & 5 deletions src/messages/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,17 @@
"title": "Профіль",
"subtitle": "Тут ви можете переглядати свій профіль, редагувати контакти, додавати посилання на облікові записи та назначати деталі прийому.",
"info": {
"title": "Дані за місцем навчання(роботи)",
"education-title": "Дані за місцем навчання",
"work-title": "Дані за місцем роботи",
"subdivision": "Підрозділ",
"group": "Група",
"grade-book": "№ залікової книги",
"study-form": "Форма навчання",
"course": "Курс навчання:",
"specialty": "Спеціальність",
"fullNameEN": "ПІБ(англійською)"
"education-form": "Форма навчання",
"study-year": "Курс навчання:",
"speciality": "Спеціальність",
"fullNameEN": "ПІБ(англійською)",
"academic-degree": "Науковий ступінь",
"academic-status": "Вчене звання"
},
"contact": {
"title": "Контакт",
Expand Down
12 changes: 12 additions & 0 deletions src/types/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const USER_CATEGORIES = {
Student: 'Студент',
Lecturer: 'НПП',
};

export const EMPLOYMENT_TYPE = {
Unknown: 'невідомо',
FullTime: 'основне',
PartTime: 'сумісник',
PartTimeInternal: 'внутрішній сумісник',
PartTimeExternal: 'зовнішній сумісник',
};
18 changes: 18 additions & 0 deletions src/types/employee-profile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { EMPLOYMENT_TYPE } from '@/types/constants';

interface Subdivision {
id: number;
name: string;
}

interface EmployeePosition {
name: string;
subdivision: Subdivision;
employment: keyof typeof EMPLOYMENT_TYPE;
}

export interface EmployeeProfile {
positions: EmployeePosition[];
academicDegree: string;
academicStatus: string;
}
15 changes: 15 additions & 0 deletions src/types/student-profile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
interface Group {
id: number;
name: string;
}

export interface StudentProfile {
speciality: string;
studyGroup: Group;
gradeBookNumber: string;
studyYear: number;
codeOfHonorSigned: boolean;
faculty: string;
status: string;
formOfEducation: string;
}
25 changes: 5 additions & 20 deletions src/types/user.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
interface Group {
id: number;
name: string;
}

interface StudentProfile {
speciality: string;
studyGroup: Group;
gradeBookNumber: string;
studyYear: number;
codeOfHonorSigned: boolean;
faculty: string;
status: string;
formOfEducation: string;
}
import { StudentProfile } from '@/types/student-profile';
import { EmployeeProfile } from '@/types/employee-profile';
import { USER_CATEGORIES } from '@/types/constants';

export interface User {
id: number;
Expand All @@ -29,10 +17,7 @@ export interface User {
intellectProfileEnabled: boolean;
intellectProfile?: string;
userCategories: (keyof typeof USER_CATEGORIES)[];
codeOfHonorSignDate: string;
studentProfile?: StudentProfile;
employeeProfile?: EmployeeProfile;
}

export const USER_CATEGORIES = {
Student: 'Студент',
Lecturer: 'НПП',
};

0 comments on commit a26e368

Please sign in to comment.