{"id":24234957,"url":"https://github.com/uniteam31/unishare-frontend","last_synced_at":"2026-04-15T10:31:32.825Z","repository":{"id":265909260,"uuid":"896843981","full_name":"uniteam31/unishare-frontend","owner":"uniteam31","description":"Coming soon...","archived":false,"fork":false,"pushed_at":"2025-02-26T14:21:20.000Z","size":1652,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-02-26T14:22:57.723Z","etag":null,"topics":["feature-sliced-design","jenkins","react","react-hook-form","typescript","webpack"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/uniteam31.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-01T12:51:36.000Z","updated_at":"2025-01-04T12:16:35.000Z","dependencies_parsed_at":"2024-12-01T13:43:49.149Z","dependency_job_id":"641e5d37-de4b-43ab-b87b-3e3c38963cc5","html_url":"https://github.com/uniteam31/unishare-frontend","commit_stats":null,"previous_names":["uniteam31/uni-share","uniteam31/unishare","uniteam31/unishare-frontend"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uniteam31%2Funishare-frontend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uniteam31%2Funishare-frontend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uniteam31%2Funishare-frontend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uniteam31%2Funishare-frontend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uniteam31","download_url":"https://codeload.github.com/uniteam31/unishare-frontend/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241864624,"owners_count":20033201,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["feature-sliced-design","jenkins","react","react-hook-form","typescript","webpack"],"created_at":"2025-01-14T17:39:06.836Z","updated_at":"2026-04-15T10:31:32.797Z","avatar_url":"https://github.com/uniteam31.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# unishare\n\n### ССЫЛКИ\n\n[DEV стенд](http://176.114.90.241/) (работает в режиме воруй-убивай)  \n[JENKINS CI/CD](https://176.114.90.241:8080/) (private)  \n[UNITEAM NOTION](https://www.notion.so/UNITEAM-1049780386b880adbbe1e3480e5159ce?pvs=4) (private)  \n[UNISHARE NOTION](https://www.notion.so/UNISHARE-1709780386b880388d2dfbbc751678c3?pvs=4) (private)  \n[YOUGILE](https://ru.yougile.com/board/kyihl3hhjnbh)  \n\n## DEVELOPER GUIDE\n### Сборка Dockerfile (для локального теста docker-compose)\n\n**ENV**: API_URL, BRANCH  \n**COMMANDS**:\n1. Сборка образа -\u003e `docker build --no-cache -t def1s/unishare-frontend --build-arg API_URL=... --build-arg BRANCH=... --build-arg NOTES_URL=... --build-arg FRIENDS_URL=... --build-arg ACCOUNT_SETTINGS_URL=... .` (точку не забывать)\n2. Push -\u003e `docker push def1s/unishare-frontend` (но смысла особо нет, в пайплайне все равно перепушит)\n3. Run -\u003e `docker run def1s/unishare-frontend`\n4. Можно взять образ из DockerHub -\u003e `docker pull def1s/unishare-frontend`\n\n### ЗАЧЕМ И КАК\nДля чистого и оптимального кода должен существовать единый набор правил и рекомендаций по разработке. В этом разделе кратко описаны\nосновные требования и практики, использующиеся при разработке модулей.\n\n#### ПРОЦЕСС РАЗРАБОТКИ\n\n1. Создается таска на [YOUGILE](https://ru.yougile.com/board/kyihl3hhjnbh)\n   1. Если задача содержит часть подзадач, то создаются подтаски.\n2. Создается ветка с номером текущей таски. Каждый коммит комментируется с указанием таски: 'UNI-XX: some changes'\n   1. Ветка ВСЕГДА имеет номер таски, даже если выполняется подтаска этой задачи. В коммите можно\nуказать 'UNI-[главный номер]-[подзадача]', но не принципиально.\n3. Задача всегда вливается через ПР в dev ветку. Если упал пайплайн, то [смотрим](https://176.114.90.241:8080/)   что не так -\u003e фиксим -\u003e повторяем пока не соберется\n4. После вливания в dev при условии успешной сборки изменения автоматически накатываются на [DEV стенд](http://176.114.90.241/)  \n5. Кайфуем\n\n#### РЕКОМЕНДАЦИИ\n1. Комментарии это **ОЧЕНЬ** хорошо, но еще лучше дробить функции на маленькие части и писать самодокументирующийся код\nна основе названий функций. Большие функции - ЭТО ПЛОХО, а большие функции без комментариев - ЭТО ОЧЕНЬ ПЛОХО, потому что\nпонятно только тому, кто это написал и только в момент написания.\n2. Писать сразу хорошо и **НИКОГДА** не откладывать что-то на рефакторинг. Хочется что-то отложить на потом, но нужно\nпомнить, что ПОТОМ - это скорее всего никогда, а кодовая база постоянно расширяется и задачи прибавляются.\n\n#### ПРАКТИКИ\n1. При написании интерфейсов мы используем префикс I, а для типов T. Интерфейсы чаще всего дублируют названия своей сущности.  \n`interface IExample`  \n`type TExample`\n2. Интерфейсы используются для описания пропсов компонента, каждый интерфейс собирается из более мелких типов.\nТипы используются для задания дополнительных свойств. Если интерфейс большой -\u003e дробим на логические типы и собираем в один.\n\n**entities/Note/model/types/note.ts**\n```\nimport { TMeta } from 'shared/types/meta';\n\n/** Поля у формы заметки */\nexport type TNoteFormFields = {\ntitle?: string;\ntext?: string;\n};\n\n/** Данные заметки */\nexport type TNodeData = TNoteFormFields \u0026 {\nauthor: string;\n};\n\n/** Целый экземпляр */\nexport interface INote extends TNodeData, TMeta {}\n```\nЧаще всего дробим интерфейс на форму, данные, не входящие в форму и мета данные.\n\n3. Если компонент (entity, widget, ...) содержит сущности, которые логически связаны с\nродителем, то наружу мы выпускаем компонент-обертку, собирающая эти сущности в\nединое целое\n\n**entities/Note/index.ts**\n```\nimport { Item } from './ui/Item/Item';\nimport { List } from './ui/List/List';\nimport { ListItem } from './ui/ListItem/ListItem';\n\nexport type { INote, TNodeData, TNoteFormFields } from './model/types/note';\n\ntype TNoteComponents = {\n\tList: typeof List;\n\tListItem: typeof ListItem;\n\tItem: typeof Item;\n};\n\n/** Экспортируем обертку для компонентов, которые связаны логически */\nexport const Note: TNoteComponents = {\n\tList,\n\tItem,\n\tListItem,\n};\n\nexport { useNoteStore } from './model/slice/useNoteStore';\n\nexport { useGetNotes } from './api/useGetNotes';\nexport { useCreateNote } from './api/useCreateNote';\nexport { useUpdateNote } from './api/useUpdateNote';\nexport { useDeleteNote } from './api/useDeleteNote';\n```\nУлучшается читаемость и нет пересечений между компонентами по типу Item, Title и т.п.\n\n4. Все формы оборачиваем в FormWrapper и прокидываем в него тип для значений (см. пункт 2)\n```\n...\n\nconst methods = useForm\u003cTLoginFormField\u003e();\n\nreturn (\n    \u003cModalUI isOpen={isOpen} onClose={onClose}\u003e\n        \u003cFormWrapper\u003cTLoginFormField\u003e methods={methods}\u003e\n            \u003cForm /\u003e\n        \u003c/FormWrapper\u003e\n    \u003c/ModalUI\u003e\n);\n```\nПолучается строгая типизация формы.\n\n5. Все состояния (загрузка, ошибки) управляются компонентом с наибольшей ответственностью за ui сущности.\nНа примере entites/Note.List заметим, что он имеет в пропсах isLoading и error, но вот виджет заметки, рисующий часть заметок,\nконтролирует сам себя, потому что entites/Note.ListItem не имеет под собой большой ответственности за ui самого виджета.\n\n6. На данный момент (пока что!) все методы по работе с бэкендом выносятся в api сущности в виде хуков. Все get запросы\nконтролируются с помощью SWR, который предоставляет стейт с состояниями, в остальных методах вручную пишем\nстейты с загрузкой и ошибкой.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funiteam31%2Funishare-frontend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funiteam31%2Funishare-frontend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funiteam31%2Funishare-frontend/lists"}