From 7ac8a2c778ff51d6587a22d18636378b96d087b3 Mon Sep 17 00:00:00 2001 From: Mikan <72257910+Mikan-DS@users.noreply.github.com> Date: Tue, 3 Jun 2025 16:52:30 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D0=BE=20=D0=B4?= =?UTF-8?q?=D0=B8=D0=BF=D0=BB=D0=BE=D0=BC=D0=B0=20=D0=94=D0=B0=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- StaticHelper/source/docs.md | 280 +++------------------------- StaticHelper/source/header.md | 15 +- StaticHelper/source/old_input.md | 253 ++++++++----------------- StaticHelper/source/working_file.md | 138 -------------- 4 files changed, 114 insertions(+), 572 deletions(-) diff --git a/StaticHelper/source/docs.md b/StaticHelper/source/docs.md index 9278b7d..3f9aa52 100644 --- a/StaticHelper/source/docs.md +++ b/StaticHelper/source/docs.md @@ -1,260 +1,40 @@ -# Требования к коду +# Введение -Используется библиотека `react-router-dom` и `react=markdown`. +В условиях динамичного развития рынка коммерческой недвижимости офисным центрам необходимо не только обеспечивать +высокий уровень обслуживания арендаторов, но и эффективно управлять внутренними процессами. Одним из ключевых +направлений деятельности является организация аренды помещений, планирование их загрузки, +своевременное обновление информации об услугах и надёжный контроль за бронированиями и платежами. -Все компоненты должны быть функциональными. -props должны быть сразу распакованы. -export без default +На практике многие офисные центры продолжают использовать устаревшие методы учёта, такие как бумажные документы или +таблицы Excel, что усложняет управление, увеличивает вероятность ошибок и снижает оперативность принятия решений. +Отсутствие единой информационной системы часто приводит к нарушению сроков аренды, +путанице в расписании, неудовлетворённости клиентов и финансовым потерям. -Пример: +Внедрение специализированного программного обеспечения для управления арендаторами, помещениями и услугами позволяет +значительно повысить эффективность работы офисного центра, минимизировать влияние человеческого фактора, +автоматизировать документооборот и укрепить доверие клиентов. Это особенно актуально в условиях цифровизации и +роста конкуренции в сегменте коммерческой недвижимости. -```tsx -export function ProfessionPage() { - const {professionId} = useParams<{ professionId: string }>(); -} -``` +Таким образом, тема данной работы обусловлена необходимостью создания современной информационной системы, которая +оптимизирует процессы аренды, обслуживания арендаторов и контроля финансовых операций в офисном центре. -Используйте современные практики React (например, хуки). -При создании новых компонентов добавьте комментарии. +Цель дипломного проекта — разработка программного продукта для автоматизации учёта и контроля деятельности офисного +центра. Приложение предоставляет возможности добавления, редактирования и удаления данных о клиентах, помещениях и +услугах, планирования графика аренды, ведения учёта договоров и контроля оплат. -Если для задачи необходимы новые типы, интерфейсы или вспомогательные компоненты - создавай их в соответвующих файлах. +Для достижения поставленной цели необходимо решить следующие задачи: -# Документария +1. Провести анализ существующих программных решений для автоматизации управления коммерческой недвижимостью, выявить их сильные и слабые стороны. +2. Определить функциональные и нефункциональные требования к разрабатываемой системе. +3. Спроектировать архитектуру программного обеспечения с учётом удобства использования, безопасности данных и масштабируемости. +4. Разработать приложение с использованием современных технологий, таких как WPF, C# и MS SQL Server. +5. Реализовать модули управления арендаторами, помещениями, договорами аренды и дополнительными услугами. +6. Внедрить систему авторизации, аутентификации и разграничения прав доступа для различных типов пользователей (администратор, менеджер, бухгалтер). +7. Подготовить и провести комплексное тестирование приложения для проверки его корректной работы и соответствия заданным требованиям. +8. Оценить эффективность разработанного решения и его влияние на процессы управления офисным центром. -## Существующие типы +Пояснительная записка дипломной работы содержит следующие разделы: введение, две главы основной части, заключение, +три раздела приложений. -`types/api.ts` -```ts -export interface ApiResponse { - body?: object, - success: boolean -} -export interface PageResponse{ - count: number; - next?: string; - previous?: string; - results: T[] -} -``` +В разделе Введения отражены актуальность темы, цель дипломной работы и задачи. -`types/common.ts` -```ts -export interface UniqueItem{ - id: number; -} - -export interface PageControl{ - items: T[] | null; - hasNext: boolean; - hasPrevious: boolean; - nextPage(): void; - previousPage(): void; -} -export interface FieldInfo { - name: string; - type: string; - title: string; - format?: string; -} -``` -`types/survey.ts` -```ts -import {UniqueItem} from "./common.ts"; - -export interface Survey extends UniqueItem{ - title: string; - description: string; -} -interface Statement extends UniqueItem{ - text: string; - score_variable: number; -} -export enum QuestionType{ - QuestionPair, - AgreementQuestion -} -export interface Question extends UniqueItem{ - questionType: QuestionType -} -export interface QuestionPair extends Question{ - statements: Statement[] -} -export interface AgreementQuestion extends Question{ - question: string; - score_variable: number; -} -export interface ScoreVariable { - id: string; - name: string; - title: string; - description: string; - survey: number; -} -export interface Profession extends UniqueItem { - name: string; - description: string; -} -export interface Specialty extends UniqueItem { - name: string; - institution: number; - link?: string; -} -export interface Institution extends UniqueItem { - name: string; -} -``` -`types/users.ts` -```ts -import {UniqueItem} from "./common.ts"; - -export type UserContextType = { - user: Account | undefined; - login: (credentials: TokenObtainPair) => Promise; - logout: () => void; -}; -export interface ContactData{ - first_name: string; - last_name?: string; - middle_name?: string; - phone?: string; - email?:string; -} -export interface Account extends UniqueItem, ContactData{ - login: string; - role?: number; - roleTitle?: string; - is_staff: boolean; - is_active: boolean; -} -export interface TokenObtainPair { - login: string; - password: string; -} -export interface TokenRefresh { - refresh: string; -} -export interface TokenVerify { - token: string; -} -export interface JwtTokenResponse { - access: string; - refresh: string; -} -``` - -## Способы запросов - -Вместо fetch запросы должны проходить при помощи специальных функций/функции - -`API/common.ts` -```ts -async function getFetch(path: string) // Get method -async function postFetch( - path: string, - body: object | FormData -) // Post method -async function patchFetch( - path: string, - body: object | FormData -) // Patch method -async function deleteFetch(path: string) // Delete method -``` - -## Хуки - -### Для загрузки данных - -Для упрощения работы с api созданы следующие хуки - -`API/hooks.ts` -```ts -function useDataPage(application:string, endpoint: string, params:{[key:string]:string|number}={}, needLoad:boolean=true):PageControl -function useData(application:string, endpoint: string, id: string|number, needLoad:boolean=true): T|null|undefined -function useCachedData(application: string, endpoint: string): (id: string | number, needLoad: boolean = true)=> T|undefined|null -``` -- application - Название модуля -- endpoint - Название объекта над которым идёт работа -- id - id искомого объекта -- params - дополнительные параметры (например фильтрация) -- needLoad - указывает нужно ли загружать список/объект прямо сейчас - - -- null - загрузка еще не происходила -- undefined - не найдено -- T (объект) - -### Для ленивой загрузки элементов - -`components/LoadingData.tsx` -```tsx -function LoadingData({data, children}: {data: object|null|undefined, children: (ReactElement | null | undefined | boolean)[]}) -``` - -Для загрузки отдельного элемента. -Если data -- null - Возвращает
Идёт загрузка...
-- undefined - 404 НЕ НАЙДЕНО -- иначе возвращает children - -`components/LoadingList.tsx` -```tsx -function LoadingList({data, listElement}: {data: UniqueItem[]|null, listElement(e:UniqueItem, i:number):unknown}) -``` - -Для загрузки списка. Если data не null - то возвращает элементы результаты `listElement` - -### Примеры - -```tsx -export function ProfessionPage() { - const { professionId } = useParams<{ professionId: string }>(); - const profession = useData('surveys', 'professions', professionId || 0); - const specialties = useDataPage('surveys', 'specialties', { profession: professionId || 0 }, !!profession); - - const institutions = useCachedData("surveys", "institutions"); - - return ( -
- -

{profession?.name}

-
- {profession?.description || ''} -
-
- {specialties.items != null ?

Где можно обучиться

:null} - ( - - )} - /> -
-
-
- ); -} -``` - -### Автодокументация -`api/hooks.ts` -```ts -/** - * Хук для получения документации swagger JSON и извлечения структур. - * @param applicationName Название модуля/приложения. - * @param endpointName Название эндпоинта. - * @returns Массив структур без ID с полями: название, тип, title, format. - */ -export function useApiDocumentation( - applicationName: string, - endpointName: string -): { schema: FieldInfo[] | null; loading: boolean; error: Error | null } -``` - - -### Авторизация - -Везде доступен хук `useUser():UserContextType | undefined ` \ No newline at end of file diff --git a/StaticHelper/source/header.md b/StaticHelper/source/header.md index dba9390..ff66997 100644 --- a/StaticHelper/source/header.md +++ b/StaticHelper/source/header.md @@ -1,14 +1,7 @@ -Ты Senior разработчик React. +Ты пишешь дипломную работу по специальности "Информационные системы и программирование". Ты должен следовать примерам которые ты получаешь +и следовать теме "Проектирование и разработка системы "Офисный центр"". Твой проект - "Office Flow". -Твоя задача - писать код под задачи (отвечай ТОЛЬКО кодом). +Ниже - то что есть на данный момент. -Я могу кидать тебе просто код или информацию. Если я не прошу писать код - отвечай только "Понял". -Код, по возможности, только тот который необходимо внести в проект. Может быть работа сразу над несколькими файлами - -Шаблон ответа кодом: - -`Путь и название файла` -```ts -// Код который должен быть в этом файле -``` +Ты пишешь в формате markdown, поэтому правильно оформляй текст. diff --git a/StaticHelper/source/old_input.md b/StaticHelper/source/old_input.md index 4556427..a68d8c9 100644 --- a/StaticHelper/source/old_input.md +++ b/StaticHelper/source/old_input.md @@ -1,189 +1,96 @@ +Это существующий код -```ts - -import { useState, useMemo, useCallback } from 'react' -import { FieldInfo } from '../types/common' -import {FiltersState, VisibilityState} from "../types/filters.ts"; - - - -/** - * Хук для управления фильтрами и видимостью колонок таблицы. - * @param schema Схема полей таблицы. - * @param initialData - * @returns Объекты состояния фильтров и видимости, а также функции для их изменения. - */ -export function useTableFilters(schema: FieldInfo[]| null, initialData: unknown[] | null) { - const [filters, setFilters] = useState({}) - const [visibleColumns, setVisibleColumns] = useState({}) - - // Инициализация видимости колонок - useMemo(() => { - if (!schema){ - return; - } - - const initialVisibility: VisibilityState = {} - schema.forEach(field => { - initialVisibility[field.name] = true - }) - setVisibleColumns(initialVisibility) - }, [schema]) - - // Обновление фильтров - const handleFilterChange = useCallback((name: string, filterPart: unknown) => { - setFilters(prev => ({ - ...prev, - [name]: { - ...prev[name], - ...filterPart - } - })) - }, []) - - // Переключатель видимости колонки - const handleColumnToggle = useCallback((name: string) => { - setVisibleColumns(prev => ({ - ...prev, - [name]: !prev[name] - })) - }, []) - - // Логика фильтрации данных, вынесенная из компонента - const filteredData = useMemo(() => { - if (!initialData || !schema){ - return ; - } - return initialData.filter(item => { - return schema.every(field => { - const value = item[field.name] - const filter = filters[field.name] - if (!filter) return true - - // Обработка по типу - if (field.type === 'string') { - if (filter.searchText) { - if (typeof value !== 'string') return false - if (!value.toLowerCase().includes(filter.searchText.toLowerCase())) return false - } - if (filter.exactMatch && filter.searchText) { - return value.toLowerCase() === filter.searchText.toLowerCase() - } - if (filter.empty !== undefined) { - const isEmpty = value === '' || value === null || value === undefined - if (filter.empty && !isEmpty) return false - if (filter.notEmpty && isEmpty) return false - } - } else if (field.format === 'date') { - const dateValue = new Date(value as string).getTime() - if (filter.fromDate) { - const fromTime = new Date(filter.fromDate).getTime() - if (dateValue < fromTime) return false - } - if (filter.toDate) { - const toTime = new Date(filter.toDate).getTime() - if (dateValue > toTime) return false - } - } else if (field.type === 'number') { - const numValue = Number(value) - if (filter.gte !== undefined && numValue < filter.gte) return false - if (filter.lte !== undefined && numValue > filter.lte) return false - } - return true - }) - }) - }, [initialData, filters, schema]) - - return { - filters, - setFilters, - visibleColumns, - setVisibleColumns, - handleFilterChange, - handleColumnToggle, - filteredData - } +```tsx +export function MainLayout() { + return ( + <> +
+ ☰ + Logo +
+
+ +
+ + ); } +``` + +```tsx +export function MainPage() { + + const surveys = useDataPage("surveys", "surveys") -export function FilteredTable({ schema, filteredData, visibleColumns}: FilteredTableProps) { return ( -
+
+

Тесты для школьников и абитуриентов

+
+ ( + {s.title} + )}/> +
- - - - {schema.map( - (field) => - visibleColumns[field.name] && ( - - ) - )} - - - - {filteredData.length > 0 ? ( - filteredData.map((item) => ( - - {schema.map( - (field) => - visibleColumns[field.name] && ( - - ) - )} - - )) - ) : ( - - - - )} - -
- {field.title} -
- {item[field.name] ?? "-"} -
- Нет данных для отображения -
+

+ Добро пожаловать на Pro-Fi Test — платформу, созданную для тех, кто стоит перед важным + выбором: какую профессию выбрать, куда поступать и кем стать. + Мы знаем, что определиться с будущим бывает непросто — особенно когда вариантов много, а уверенность в + правильности выбора не всегда есть. + Наша цель — сделать этот путь понятнее, интереснее и максимально персонализированным. +

+

+ Pro-Fi Test — это не просто набор тестов. Это интеллектуальный гид в мире профессий, который поможет + вам: +

    +
  • Узнать себя лучше: выявить свои сильные стороны, склонности и скрытые таланты;
  • +
  • Познакомиться с миром современных профессий через призму реальных навыков и интересов;
  • +
  • Понять, какие специальности подходят именно вам, исходя из ваших целей и возможностей;
  • +
  • Сэкономить время на выборе направления обучения и сосредоточиться на главном — вашем развитии. +
  • +
+

+

+ Независимо от того, стоите ли вы на пороге выпускного класса, подаёте документы в вуз или уже начали + обучение в колледже, + Pro-Fi Test будет с вами на каждом этапе. Мы верим, что у каждого есть своё уникальное + призвание — и помогаем найти его без страха, сомнений и лишней путаницы. +

+

+ Пройдите наш тест уже сегодня и сделайте первый шаг к осознанному и уверенному выбору своей + профессиональной дороги! +

- ) + ); } - ``` +Создай css файлы для них, ниже svg из figma - - -```ts -const { - filters, - handleFilterChange, - visibleColumns, - handleColumnToggle, - filteredData - } = useTableFilters(schema, dataPage.items) - - - const handleExport = async () => { - if (!filteredData || filteredData.length === 0) { - alert('Нет данных для экспорта') - return - } - - - const blob = new Blob([buffer], { - type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - }) - saveAs(blob, "Отчёт.") - }; - -``` - - -в handleExport сохранять csv \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + diff --git a/StaticHelper/source/working_file.md b/StaticHelper/source/working_file.md index c92d0ca..e69de29 100644 --- a/StaticHelper/source/working_file.md +++ b/StaticHelper/source/working_file.md @@ -1,138 +0,0 @@ -`components/useTableFilters.tsx` -```ts -// добавьте новую функцию для экспорта CSV -export function useTableFilters(schema: FieldInfo[]| null, initialData: unknown[] | null) { - const [filters, setFilters] = useState({}) - const [visibleColumns, setVisibleColumns] = useState({}) - - // Инициализация видимости колонок - useMemo(() => { - if (!schema){ - return; - } - - const initialVisibility: VisibilityState = {} - schema.forEach(field => { - initialVisibility[field.name] = true - }) - setVisibleColumns(initialVisibility) - }, [schema]) - - // Обновление фильтров - const handleFilterChange = useCallback((name: string, filterPart: unknown) => { - setFilters(prev => ({ - ...prev, - [name]: { - ...prev[name], - ...filterPart - } - })) - }, []) - - // Переключатель видимости колонки - const handleColumnToggle = useCallback((name: string) => { - setVisibleColumns(prev => ({ - ...prev, - [name]: !prev[name] - })) - }, []) - - // Функция экспорта данных в CSV - const handleExportCSV = useCallback(() => { - if (!initialData || !schema || initialData.length === 0) { - alert('Нет данных для экспорта') - return - } - - const visibleFields = schema.filter(field => visibleColumns[field.name]) - const header = visibleFields.map(field => `"${field.title.replace(/"/g, '""')}"`).join(';') - - const rows = initialData - .filter(item => schema.every(field => { - const value = item[field.name] - const filter = filters[field.name] - if (!filter) return true - - if (field.type === 'string') { - if (filter.searchText) { - if (typeof value !== 'string') return false - if (!value.toLowerCase().includes(filter.searchText.toLowerCase())) return false - } - if (filter.exactMatch && filter.searchText) { - return value.toLowerCase() === filter.searchText.toLowerCase() - } - if (filter.empty !== undefined) { - const isEmpty = value === '' || value === null || value === undefined - if (filter.empty && !isEmpty) return false - if (filter.notEmpty && isEmpty) return false - } - } else if (field.format === 'date') { - const dateValue = new Date(value as string).getTime() - if (filter.fromDate) { - const fromTime = new Date(filter.fromDate).getTime() - if (dateValue < fromTime) return false - } - if (filter.toDate) { - const toTime = new Date(filter.toDate).getTime() - if (dateValue > toTime) return false - } - } else if (field.type === 'number') { - const numValue = Number(value) - if (filter.gte !== undefined && numValue < filter.gte) return false - if (filter.lte !== undefined && numValue > filter.lte) return false - } - return true - })) - .map(item => { - const row = visibleFields.map(field => { - const val = item[field.name] - // Обработка null/undefined - const strVal = val !== undefined && val !== null ? String(val) : '' - // Экранирование кавычек - return `"${strVal.replace(/"/g, '""')}"` - - }) - return row.join(';') - }) - - const csvContent = [header, ...rows].join('\n') - // Создаем ссылку для скачивания - const blob = new Blob([csvContent], { type: 'text/csv' }) - const url = URL.createObjectURL(blob) - const link = document.createElement('a') - link.href = url - link.download = 'export.csv' - document.body.appendChild(link) - link.click() - document.body.removeChild(link) - URL.revokeObjectURL(url) - }, [initialData, schema, filters, visibleColumns]) - - return { - filters, - setFilters, - visibleColumns, - setVisibleColumns, - handleFilterChange, - handleColumnToggle, - filteredData, - handleExportCSV // добавьте сюда - } -} -``` - -`Ваш файл, где вызывается handleExport` (примеры использования) -```ts -const { - filters, - handleFilterChange, - visibleColumns, - handleColumnToggle, - filteredData, - handleExportCSV // новая функция -} = useTableFilters(schema, dataPage.items) - -const handleExport = async () => { - handleExportCSV() -} -``` \ No newline at end of file