Skip to content

Project documentation#268

Open
Awakich wants to merge 24 commits into
devfrom
project-documentation
Open

Project documentation#268
Awakich wants to merge 24 commits into
devfrom
project-documentation

Conversation

@Awakich
Copy link
Copy Markdown
Collaborator

@Awakich Awakich commented May 13, 2026

No description provided.

Awakich added 24 commits May 7, 2026 13:48
    aliases, application layering, cross-cutting blocks, environments,
    prod/dev-stage cookie isolation, build/CI, routing entry points,
    kanban-disabled note, planned per-module docs index).
  - Replace root README stub (Angular CLI 13 leftover) with a short
    pointer to docs/.
Add docs/core/ with five files covering all of projects/core/src:

- services.md: 11 services with full method tables, behaviour notes,
  known bugs (LoggerService PRODUCTION DI token mismatch, ErrorService
  throwNotFount typo, unused deps in GlobalErrorHandlerService) and
  architectural debt (core depends on social_platform).
- interceptors-providers.md: BearerToken (refresh flow, blob handling,
  parallel-401 dedup), Camelcase (FormData passthrough), Logging;
  the three InjectionTokens; missing WEBSOCKET_* tokens.
- pipes.md: 16 pipes in one table; DayjsPipe action types;
  pipes/index.ts gaps.
- guards-models.md: 3 active guards (kanban guard noted as disabled);
  ErrorCode, ErrorMessage (full text table), ApiError, subscription
  models.
- consts.md: folder layout, naming rules (moved from deleted README),
  every list/filter/navigation/other constant tabulated with
  kanban-only tags; "how to add a new constant" guide.

Mark the five core/ docs as done in docs/PROJECT.md index.

Drop README stubs:
- projects/core/README.md (superseded by docs/core/*)
- projects/core/src/consts/README.md (naming rules folded into
  docs/core/consts.md)

No source changes. JSDoc/inline comments will be a separate phase.
Add docs/uilib.md covering all of projects/ui/src:

- Folder layout, exports through public-api, and the discrepancy between
  the uilib alias surface (only ./lib/components) and what consumers
  actually need (User model is reachable only by deep import).
- Component table with selector, kind, all inputs/outputs.
- Per-component sections for layout (Sidebar, ProfileControlPanel,
  ProfileInfo, InviteManageCard, EmptyManageCard) and primitives
  (Avatar, Back, IconComponent attribute directive with appSquare/
  appViewBox/appWidth/appHeight behaviour).
- NavItem interface for SidebarComponent.
- User model + note that it duplicates social_platform/domain/auth/user.model.
- Architectural debt: ui-sidebar selector inconsistency, EmptyManageCard
  not re-exported, User duplication, uilib/models alias mismatch,
  AvatarComponent url required vs optional type.

Mark docs/uilib.md as done in docs/PROJECT.md index.

Drop projects/ui/README.md - superseded.

No source changes.
Add docs/social-platform/architecture.md covering everything in
projects/social_platform/src/app/:

- Folder layout per layer (domain / api / infrastructure / ui).
- Dependency rules and the boundary every layer must respect.
- domain/ - abstract-class ports vs interfaces, why and how.
- api/ - use-cases (one execute method, returns Result), facades
  (signal AsyncState), UI-info services (computed-only).
- infrastructure/ - repositories with EntityCache, HTTP adapters,
  per-module DI providers binding ports to implementations.
- ui/ - routes/pages/widgets/primitives/services split.
- utils/ - full inventory with kanban-only tags.
- Cross-cutting building blocks: AsyncState, Result, toAsyncState,
  EventBus, EntityCache, LoggingInterceptor + LoggerService,
  GlobalErrorHandler.
- app.config.ts breakdown: provider order, HTTP interceptor stack,
  per-module DI sets.
- Actual HTTP interceptor order (Camelcase, Bearer, Logging) with
  rationale; corrects the inaccurate ordering note in
  docs/core/interceptors-providers.md.
- Import conventions: alias table, no deep cross-project imports.
- Naming and structural conventions.
- Entry points: main.ts, app.component, app.config, app.routes.

Mark docs/social-platform/architecture.md as done in docs/PROJECT.md
index.

Drop projects/social_platform/README.md - it described the
pre-refactor structure (auth/, office/projects/list, office/chat,
office/feed, office/members, etc.) which moved into ui/pages/...
in commit be9344b; nothing salvageable.

No source changes.
Add docs/social-platform/shared.md covering the cross-module pieces of
projects/social_platform/src/app:

- domain/shared/: AsyncState (full discriminator + helpers + type
  guards + previous semantics), Result (ok/fail), toAsyncState
  operator, EntityCache (getOrFetch/invalidate/clear with shareReplay),
  EventBus (emit/on with auto-debug logging), DomainEvent base
  contract.
- domain/file/: FileModel.
- domain/other/: ApiPagination, FilterFieldConfig + FilterConfig +
  UnifiedOption, Navigation, Notification.
- utils/: full inventory of all 21 helpers with signature, behaviour
  and call-site notes; explicit kanban-only tags on getActionType /
  getPriorityType.
- Architectural debt list: typos (days-untit, maxAttemps), under-typed
  any returns (inviteToProjectMapper, FilterFieldConfig), duplicate
  breakpoint definitions, EntityCache non-null assertion, etc.

Mark docs/social-platform/shared.md as done in docs/PROJECT.md index.

No source changes.
Add docs/social-platform/ui-primitives.md and ui-widgets.md covering
all 22 atoms in projects/social_platform/src/app/ui/primitives/ and
all 20 widgets in projects/social_platform/src/app/ui/widgets/:

- ui-primitives.md: full input/output table for every primitive,
  CVA marker, defaults; per-component notes for IconComponent
  attribute directive, ModalComponent open setter, DropdownComponent
  with kanban coupling note, AutoCompleteInputComponent generics,
  CVA list. Architectural debt around dropdown-kanban coupling,
  AvatarComponent.url required-but-optional, missing index.ts entries.
- ui-widgets.md: input/output/usage table for every widget; per-widget
  notes for DeatilComponent (universal detail header for project/
  program/profile, smart-but-classified-as-widget), InfoCardComponent
  type polymorphism, ChatWindow + MessageInput pair, filter widgets
  (no inputs, work via own services and query params),
  NewsForm + NewsCard pair, skill triad (group/spec/basket),
  ProjectNavigation stepper, HeaderComponent, CookieConsent.
  Architectural debt around DeatilComponent / InfoCardComponent
  typos (kept on purpose), filter widgets being smart, Output type
  shadowing TS keyword, etc.

Mark both docs as done in docs/PROJECT.md index.

Drop projects/social_platform/src/app/ui/README.md - it described
form/select/input components in flat text without inputs/outputs and
mentioned RangeInput/NumSlider that no longer exist; superseded by
the two docs above.

No source changes.
Add docs/modules/auth.md covering the auth vertical:

- domain/auth: User (mega-class with role branches and subscription),
  Achievement / Education / WorkExperience / UserLanguages / UserRole,
  Tokens, LoginResponse / RefreshResponse / RegisterResponse,
  RegisterRequest, PasswordValidationErrors. Commands (LoginCommand,
  RegisterCommand) and discriminated-union Results (LoginError,
  RegisterError with validation_error fan-out, PasswordError).
- api/auth/use-cases: LoginUseCase, RegisterUseCase, ResendEmailUseCase,
  ResetPasswordUseCase, SetPasswordUseCase, DownloadCvUseCase - all
  return Result<T, E> with full error mapping.
- api/auth/facades: AuthInfoService (root, holds profile/roles streams),
  AuthUIInfoService (page-scoped, all forms + signal AsyncState),
  AuthLoginService, AuthRegisterService, AuthPasswordService,
  AuthEmailService (with countdown timer + magic-link handling).
- api/auth/profile.service.ts: legacy CRUD for achievements + skill
  approval, marked as architectural debt.
- infrastructure/repository/auth: AuthRepository with three
  ReplaySubject streams, plainToInstance(User) on every payload.
- infrastructure/adapters/auth: full HTTP endpoint table for
  /api/token, /auth, /auth/users surfaces.
- ui/routes/auth: lazy AUTH_ROUTES with /verification handled outside
  the AuthComponent shell to support magic-link tokens in query.
- ui/pages/auth: AuthComponent layout + 7 child pages (login, register,
  email-verification, confirm-email, reset-password, set-password,
  confirm-password-reset) with their facades and providers.
- Consumers section: who outside the module touches the port.
- Known issues: core depending on domain/auth, ?adress= typo kept on
  purpose, saveAvatar trailing-slash, narrow unknown error in
  Resend/Reset use-cases, Achievement.files polymorphism, etc.

Mark docs/modules/auth.md as done in docs/PROJECT.md index.

Drop projects/social_platform/src/app/ui/pages/auth/README.md - the
component descriptions there are flat-text without inputs/outputs and
duplicate the new doc.

No source changes.
Add docs/modules/profile.md covering the profile vertical:

- domain/profile: ProfileNews model + ProfileNewsRepositoryPort.
  Profile (User) edit relies on AuthRepositoryPort - no separate port.
- api/profile/use-cases: 7 news use-cases (Fetch/GetDetail/Add/Edit/
  Delete/ToggleLike/Read). ReadProfileNewsUseCase de-dupes through
  StorageService(sessionStorage[readNews]).
- api/profile/facades:
  - detail: ProfileDetailInfoService, ProfileDetailUIInfoService
    (user signal, isProfileEmpty/Fill, directions for direction-card,
    isShowModal), ProfileDetailProjectsInfoService.
  - edit: ProfileFormService (root, holds the FormGroup), plus 5
    page-scoped facades (Main/Education/Experience/Skills/
    Achievements) coordinated by ProfileEditInfoService with step
    routing, userTypeMap for role branches, error modals.
- infrastructure/repository/profile: ProfileNewsRepository with
  plainToInstance + readNews session-storage cache.
- infrastructure/adapters/profile: HTTP endpoint table for
  /auth/users/<id>/news/* surface.
- infrastructure/di: PROFILE_NEWS_PROVIDERS.
- ui/routes/profile: PROFILE_DETAIL_ROUTES with ProfileDetailResolver
  (forkJoin user + calculateProfileProgress) and ProfileMainResolver
  (news detail).
- ui/pages/profile:
  - detail: ProfileMainComponent split into left/mid/right side
    components, ProfileNewsComponent for /news/:newsId.
  - edit: ProfileEditComponent with five step-components
    (main / education / experience / skills / achievements),
    integrated through <app-project-navigation> stepper.
- Edit flow walkthrough: from Edit click to updateProfile() with
  the dayjs/phoneNumber TODO cross-references to merge memory.
- Consumers and known issues (edit flow split across facades,
  legacy ProfileService coupling, missing profile.repository.port,
  ProfileMainResolver naming).

Mark docs/modules/profile.md as done in docs/PROJECT.md index.

No source changes.
Add docs/modules/skills.md covering the technical-skills vertical:

- Disambiguation up front: this module = /core/skills/* under the
  main API (programming, design, etc.), separate from
  SkillsApiService / SubscriptionPlansService which lives under
  SKILLS_API_URL for the subscription/payments domain.
- domain/skills: Skill (with Approve[] confirmations chain),
  SkillsGroup (category -> skills), SkillsRepositoryPort.
- api/skills/use-cases: GetSkillsNestedUseCase, SearchSkillsUseCase
  - both collapse all errors into { kind: server_error }.
- api/skills/facades: SkillsInfoService (root) - holds inlineSkills
  signal for autocomplete, exposes onAddSkill/onRemoveSkill/
  onToggleSkill helpers that mutate a passed FormGroup
  (deliberate: skills widgets are dumb, the FormGroup mutation
  is concentrated here).
- infrastructure/repository/skills: thin SkillsRepository passthrough
  with no EntityCache (note as debt - a single nested list is
  refetched on every consumer subscription).
- infrastructure/adapters/skills: HTTP endpoint table for
  /core/skills/nested and /core/skills/inline (with
  name__icontains query and limit/offset pagination).
- Skills widgets <app-skills-group> / <app-skills-basket>
  consumption: inputs/outputs and where they are wired.
- Consumers list across profile-edit, project-edit (vacancy step),
  members-filters, onboarding stage-two, and (disabled) kanban
  task-detail.
- Known issues: missing shareReplay on getSkillsNested,
  onSearchSkill hard-codes limit=1000, SkillsInfoService bypasses
  use-cases, approve/unapprove still on legacy ProfileService.

Mark docs/modules/skills.md as done in docs/PROJECT.md index.

No source changes.
Add docs/modules/specializations.md covering the specializations
vertical:

- Disambiguation: specializations = role/profession (Frontend dev,
  Designer, PM), distinct from skills (technical know-how).
- domain/specializations: Specialization (id+name), SpecializationsGroup
  (group+specializations[]), SpecializationsRepositoryPort (nested +
  inline search with limit/offset/name__icontains).
- No use-cases - facade goes straight to the port. Marked as debt
  vs the parallel skills module which already has use-cases.
- api/specializations/facades: SpecializationsInfoService (root),
  pure passthrough.
- infrastructure/repository/specializations: thin pass-through repo
  without EntityCache or class-transformer.
- infrastructure/adapters/specializations: HTTP endpoint table for
  /auth/users/specializations/nested and /inline (note that
  specializations sit under auth/users on the backend).
- Widget <app-specializations-group> reference back to ui-widgets doc.
- Consumers: profile-edit (ProfileFormService.inlineSpecs),
  onboarding stage-one, members search through api/searches.
- Known issues: missing use-cases, missing shareReplay,
  passthrough facade adds no value yet.

Mark docs/modules/specializations.md as done in docs/PROJECT.md index.

No source changes.
Add docs/modules/industry.md for the industries reference (IT,
Fintech, Education, Urbanism, etc.) used to classify projects,
vacancies, programs:

- domain/industry: Industry (id+name) and IndustryRepositoryPort
  with a Signal industries cache exposed alongside getAll() +
  synchronous getOne(id).
- No use-cases; facade is a thin passthrough (debt vs skills).
- api/industry/facades: IndustryInfoService re-exports the signal
  and the two repository methods.
- infrastructure/repository/industry: IndustryRepository fills the
  signal in tap() of getAll(), runs plainToInstance, has an unused
  EntityCache<Industry> (debt - dead code).
- infrastructure/adapters/industry: single endpoint GET /industries/
  returning the full flat list (no pagination/search on backend).
- Consumers: project detail, feed (new-project, open-vacancy),
  program rating-card, info-card widget, projects-filter,
  office shell (warms the cache), project edit form.
- Known issues: missing use-cases, passthrough facade, dead
  EntityCache, getOne(id) returns undefined synchronously when
  cache is empty (callers must dispatch getAll() first).

Mark docs/modules/industry.md as done in docs/PROJECT.md index.

No source changes.
Add docs/modules/member.md for the platform participants list:

- Disambiguation: member = User with userType === 1; userType 2/3/4
  are mentor/expert/investor and use a parallel getMentors()
  endpoint with user_type=2,3,4 filter.
- domain/member: only the MemberRepositoryPort - no own model
  (reuses User from auth).
- api/member/use-cases: GetMembersUseCase (Result with
  get_members_error). getMentors has no use-case yet.
- api/member/facades:
  - MembersInfoService (page-scoped) - reactive search and
    filter forms, debounce, infinite scroll on container
    scroll, query-param sync.
  - MembersUIInfoService (page-scoped) - members$ AsyncState
    signal with previous-during-loading semantics, members
    computed, totalCount, take, page, searchForm, filterForm
    (keySkill, speciality, age range, isMosPolytechStudent).
  - MentorsUIInfoService - dead code, no consumer.
- infrastructure/repository/member: pass-through with
  plainToInstance(User).
- infrastructure/adapters/member: GET /auth/public-users/ with
  user_type discriminator and limit/offset/filter params.
- Routes attached inside office shell, no separate members.routes.
- Pages: MembersComponent + MembersFiltersComponent (autocomplete
  for key skill and speciality through skills/searches).
- Resolver MembersResolver fetches the first 20.
- Consumers: info-card with type=members, project-team-step.
- Known issues: dead MentorsUIInfoService, missing GetMentorsUseCase,
  filterForm.keySkill/speciality marked required by mistake,
  untyped Record<string, ...> filter params.

Mark docs/modules/member.md as done in docs/PROJECT.md index.

No source changes.
Add docs/modules/project.md - the largest module: 8 sub-domains
across ports/repos/DI, 33 use-cases, 14+ facades for the edit flow,
9 repositories, 8 HTTP adapters, multiple page hierarchies.

- domain/project: Project mega-model (with PartnerProgramInfo,
  ProjectCount, ProjectStep), Collaborator, Goal+ResponsibleInfo,
  Partner+PartnerDto+Company, Resource+ResourceDto, ProjectAssign,
  ProjectAdditionalFields, ProjectSubscriber, the 4 rating models,
  step.model and the 4 wrapper-types around skills/specializations.
- domain/project/commands: UpdateFormCommand.
- domain/project/events: ProjectCreated, ProjectDeleted,
  ProjectSubscribed, ProjectUnSubscribed (sic), and
  RemoveProjectCollaborator.
- 9 repository ports: project, collaborators, goals, news, partner,
  program (assign-to-program + send-fields), rating, resource,
  subscription. Methods enumerated in tables.
- 33 use-cases tabulated by responsibility: list/get/create/delete,
  goals CRUD, partners CRUD, resources CRUD, subscribers,
  subscriptions add/delete (event-emitting), 7 news use-cases,
  competitive-submission, additional-fields, leave/remove-collab.
- api/project/facades: list / dashboard / detail (with sub-tabs:
  info, work-section, chat) / edit. Edit flow detail: ProjectFormService
  (root) + ProjectFormFactory + ProjectFormAutosaveService and 8
  step-specific services (Main/Contacts/Achievements/Goals/
  Partner+Resources/Vacancy/Team/Additional).
- ProjectRepository: showcase of EventBus + EntityCache - listens
  to its own ProjectCreated/Deleted/Subscribed/Unsubscribed and
  RemoveProjectCollaborator events plus the three vacancy-response
  events to invalidate the cache automatically.
- HTTP endpoint table grouped by adapter (project, collaborators,
  goals, news, partner, program, rating, resource).
- Routes: PROJECTS_ROUTES (dashboard/my/all/subscriptions/invites/
  edit at root) and PROJECT_DETAIL_ROUTES (info/news/vacancies/
  team/work-section/chat) with the kanban route explicitly noted
  as commented-out.
- Pages: full inventory across detail/info three-column layout,
  detail/{vacancies,team,work-section,chat,news-detail}, edit
  with 6 step components.
- Consumers and known issues: typos kept (projecId, UnSubscribed),
  duplicate domain wrapper types, legacy ProjectsService alongside
  use-cases, edit-flow facade sprawl, autosave with no retry queue.

Mark docs/modules/project.md as done in docs/PROJECT.md index.

No source changes.
Add docs/modules/vacancy.md covering vacancies + responses:

- domain/vacancy: Vacancy (with project + requiredSkills + salary
  string + work format/schedule), VacancyResponse (whyMe + isApproved
  + accompanyingFile), VacancyRepositoryPort with 11 methods.
- 6 domain events: VacancyCreated/Updated/Delete (sic) plus
  SendVacancyResponse / AcceptVacancyResponse / RejectVacancyResponse
  consumed by ProjectRepository for cache invalidation.
- 10 use-cases: GetVacancies, GetVacancyDetail, GetMyVacancies,
  PostVacancy (emits Created), UpdateVacancy (emits Updated),
  DeleteVacancy (emits Delete), SendVacancyResponse (emits Send),
  GetProjectResponses, AcceptResponse / RejectResponse with their
  events.
- Facades: VacancyInfoService + VacancyUIInfoService for the list
  page (search/filter forms with debounce + query-param sync,
  infinite scroll, listType all/my), VacancyDetailInfoService +
  VacancyDetailUIInfoService for detail page (sendForm with
  ValidationService, ExpandService for description, modal state).
- Repository: pass-through with plainToInstance + EntityCache,
  EventBus subscriptions for own VacancyCreated/Updated/Delete
  (note: VacancyCreated invalidates by projectId while cache keys
  by vacancyId - probable bug).
- HTTP endpoint table for /vacancies/* and /projects/<id>/responses
  surfaces.
- Routes: VACANCIES_ROUTES (all + my + detail), VACANCY_LIST_ROUTES
  (my), VACANCIES_DETAIL_ROUTES.
- Pages: VacanciesComponent shell, VacanciesListComponent (shared
  for all/my, switches by URL), VacanciesDetailComponent +
  VacancyInfoComponent + left/right side, ResponseCardComponent.
- Resolvers VacanciesResolver / VacanciesMyResolver /
  VacanciesDetailResolver.
- Widgets <app-vacancy-card>, <app-project-vacancy-card>,
  <app-vacancy-filter> referenced back to ui-widgets doc.
- Consumers: project-edit vacancy-step, project-detail
  vacancies/work-section, feed/open-vacancy, info-card.
- Known issues: VacancyDelete naming asymmetry, salary-as-string,
  CreateVacancyDto living in api/project/dto, no listType @input
  in VacanciesListComponent, etc.

Mark docs/modules/vacancy.md as done in docs/PROJECT.md index.

No source changes.
Add docs/modules/invite.md covering project invitations:

- domain/invite: Invite (project + role + specialization +
  motivationalLetter + isAccepted + user/sender), two commands
  (SendForUserCommand, UpdateInviteCommand), three domain events
  (AcceptInvite/RejectInvite/RevokeInvite) all with factory functions.
- InviteRepositoryPort with 7 methods.
- 7 use-cases: SendForUser, RevokeInvite (emits Revoke),
  AcceptInvite (emits Accept), RejectInvite (emits Reject),
  UpdateInvite, GetMyInvites, GetProjectInvites.
- Repository: pass-through with plainToInstance, plus
  myInvitesCount$ BehaviorSubject decremented on AcceptInvite /
  RejectInvite events for the header badge.
- HTTP endpoint table for /invites/* surface, including the
  ?user=any sentinel in getByProject.
- No own routes or pages - invites are surfaced through the
  header dropdown (uilib's app-profile-control-panel +
  app-invite-manage-card), in pages/projects/list?type=invites,
  and inside pages/projects/edit project-team-step.
- Widgets cross-reference: app-invite-manage-card (uilib),
  app-info-card with type=invite.
- Consumers across project-edit team-step, projects list,
  inviteToProjectMapper util.
- Known issues: RevokeInvite event has no listener, AcceptInvite
  does not invalidate ProjectRepository (asymmetric vs
  RemoveProjectCollaborator), myInvitesCount$ has no push-update,
  inconsistent trailing slashes, ?user=any sentinel parameter,
  port-vs-adapter type mismatch on revokeInvite return type.

Mark docs/modules/invite.md as done in docs/PROJECT.md index.

No source changes.
Add docs/modules/program.md covering partnership programs:

- domain/program: Program (full set of dates - registration ends,
  start, finish, project submission, evaluation; isUserManager /
  isUserMember flags; courses[] back-reference, registrationLink,
  materials[]), ProgramDataSchema (key-value config), ProgramTag.
- partner-program-fields.model: PartnerProgramFields (dynamic
  form fields per program), PartnerProgramFieldsValues,
  ProjectNewAdditionalProgramFields with snake_case quirks.
- ProgramRepositoryPort (13 methods including the
  submitCompettetiveProject typo) + ProgramNewsRepositoryPort.
- 22 use-cases: GetPrograms / GetActualPrograms / GetProgram /
  Register / GetDataSchema / GetProgramFilters /
  CreateProgramFilters / GetAllProjects / GetAllMembers /
  ApplyProjectToProgram / AssignProjectProgram /
  ParticipatingProgram / GetProjectRatings /
  FilterProjectRatings / RateProject and 6 news use-cases
  (FetchNews / AddNews / EditNews / DeleteNews / ReadNews /
  ToggleLike).
- Facades: ProgramInfoService (root), ProgramMainInfoService +
  UI for the all-programs list, ProgramDetailMainService + UI
  for the detail main page, ProgramDetailListInfoService + UI
  for the polymorphic projects/members/rating list.
- Repositories: pass-through with EntityCache for getOne;
  program-news with StorageService de-dup like profile/project.
- Two HTTP endpoint tables for /programs/* and
  /programs/<id>/news/*.
- Routes: PROGRAM_ROUTES (all + lazy detail), PROGRAM_DETAIL_ROUTES
  (main / projects / members / projects-rating + register
  outside the DeatilComponent shell).
- Pages: ProgramComponent shell, ProgramMainComponent +
  ProgramCardComponent, ProgramDetailMainComponent,
  ProgramListComponent (polymorphic by listType),
  ProgramProjectsFilterComponent, RatingCardComponent +
  ProjectRatingComponent for expert evaluation,
  ProgramRegisterComponent with dynamic form from data schema.
- Resolvers wired per route.
- Widgets cross-reference: app-detail (program mode),
  app-program-links, app-news-card, app-news-form,
  app-info-card type=rating.
- Consumers: project-edit additional-step (program fields),
  project-detail (partnerProgram), course-detail
  (partnerProgramId), widgets/detail, User.programs.
- Known issues: Cmpettetive typo, untyped applyProjectToProgram,
  snake_case in ProjectNewAdditionalProgramFields, value_text
  named text but holds bool too, Program.tag string vs
  ProgramTag class inconsistency, news duplicating profile/project
  structures (candidate for unified domain/news/).

Mark docs/modules/program.md as done in docs/PROJECT.md index.

No source changes.
Add docs/modules/courses.md covering courses + lessons + tasks:

- domain/courses: full type tree CourseCard / CourseDetail /
  CourseStructure / CourseModule / CourseLessons / CourseLesson /
  Task / Option / TaskAnswerResponse, with status / progressStatus
  / actionState / accessType union types.
- Task answer types tabulated: text, text_and_files, single_choice,
  multiple_choice, files, informational - each mapped to the
  corresponding lesson/shared/* component.
- TaskAnswerSubmitted domain event listened by ProjectRepository.
- Two ports: CoursesRepositoryPort (HTTP) and SeenModulesStoragePort
  (the only non-HTTP port - localStorage-backed flag for the
  "module completed" celebration modal, key
  course_<courseId>_module_<moduleId>_complete_seen).
- 5 use-cases: GetCourses, GetCourseDetail, GetCourseStructure,
  GetCourseLesson, SubmitTaskAnswer (emits TaskAnswerSubmitted).
- Facades:
  - CoursesListInfoService + UI for the all-courses list.
  - CourseDetailInfoService + UI - parallel detail+structure fetch
    via forkJoin in resolver, applyCourseData triggers the
    seen-modules check, redirectToProgram for the back-link.
  - LessonInfoService + UI - per-lesson controller with
    currentTaskId/activeTaskId, completedTaskIds Set,
    isDone/isClickable/isViewingCompleted helpers,
    lessonOrder computed via injected CourseDetailUIInfoService
    (DI hierarchy parent-child).
- Repository: pass-through with two EntityCaches (detail and
  structure separately). postAnswerQuestion emits
  TaskAnswerSubmitted via EventBus.
- HTTP endpoint table for /skills/courses/* and /skills/lessons/*
  and /skills/tasks/* surface (note: /skills prefix is legacy,
  the skills sub-project itself is removed).
- Routes: COURSES_ROUTES (all + lazy detail), COURSE_DETAIL_ROUTES
  (info + lazy lesson) with runGuardsAndResolvers: always,
  LESSON_ROUTES (single :lessonId + /results child).
- Pages: CoursesListComponent, CourseDetailComponent (provides
  the detail+structure pair), CourseInfoComponent with
  CourseModuleCard + CircleProgressBar, LessonComponent (provides
  LessonInfoService + LessonUIInfoService and renders the right
  task component conditionally), TaskCompleteComponent for results,
  five lesson task components.
- Widget cross-reference: app-course-about.
- Consumers: program (Program.courses[] back-reference), widgets/detail
  for course-program navigation, ProjectRepository listening for
  TaskAnswerSubmitted.
- Known issues: /skills URL legacy, Task.answerType not unioned,
  analyticsStub: any placeholder, app-detail selector conflict in
  CourseInfoComponent vs widget, SeenModulesStoragePort sync API
  doc, lessonOrder missing on the API payload, lessonId smuggled
  into the use-case via facade rather than command.

Mark docs/modules/courses.md as done in docs/PROJECT.md index.

No source changes.
Add docs/modules/news.md as a cross-cutting overview that ties
together the four news shapes used in the app:

- domain/news/article.model.ts: New class (singular - despite the
  filename being article) used for marketing articles in feed.
  Cross-references the three feature-owned news domains:
  - project-news (in docs/modules/project.md)
  - profile-news (in docs/modules/profile.md)
  - program-news (in docs/modules/program.md)
- api/news/news-info.service.ts: shared root-provided
  NewsInfoService with news$ AsyncState signal and apply* helpers
  (applySetNews / applyAddNews / applyUpdateNews / applyDeleteNews
  / applyEditNews / applyLikeNews) so consumers can plug their own
  use-case results into a single UI source of truth.
  applyLikeNews documented as optimistic mutation with manual rollback.
- Widgets reference: <app-news-card> input/output contract and the
  resourceLink pattern (segments differ per owner type), <app-news-form>
  with onResetForm / onCloseEditMode helpers.
- Note that there are no shared HTTP endpoints - each owner type
  hits its own /<owner>/<id>/news/* surface.
- Consumers across project-detail, profile-detail, program-detail,
  feed.
- Known issues: FeedNews living in domain/project/, New naming,
  triple-copy of news repository ports/use-cases, optimistic
  applyLikeNews without auto-rollback, fake CDN URLs in
  static default().

Mark docs/modules/news.md as done in docs/PROJECT.md index.

No source changes.
Add docs/modules/feed.md covering the global content feed:

- domain/feed/feed-item.model.ts: FeedProject (project preview
  for feed cards), FeedItemType (vacancy / news / project),
  FeedItem discriminated union by typeModel with content shapes
  per type (FeedProject, Vacancy, FeedNews + contentObject ref).
- FeedRepositoryPort with single fetchFeed(offset, limit, type)
  method. Type filter joins values with FILTER_SPLIT_SYMBOL "|".
- 3 use-cases: FetchFeedUseCase delegates to repository,
  ToggleFeedLikeUseCase + ReadFeedNewsUseCase dispatch to the
  three news repositories (project / profile / program) based
  on FeedItem.typeModel and contentObject.id - because the
  backend has no centralized like/read endpoint for feed.
- Facades: FeedInfoService (page-scoped, IntersectionObserver
  for infinite scroll, query param sync, optimistic
  applyToggleLike), FeedUIInfoService (feedItems$ AsyncState,
  count, offset, take=10, has-more).
- Repository + adapter: thin pass-through for GET /feed/?limit&
  offset&type with type encoded as pipe-joined string.
- Routes: attached inside office shell, no dedicated feed.routes.
  FeedResolver loads first 10 with the default filter.
- Pages: FeedComponent main with @switch by typeModel,
  NewProjectComponent for project entries (uses
  IndustryInfoService for industry name), OpenVacancyComponent
  for vacancy entries, AdvertCardComponent for marketing inserts.
  News entries reuse <app-news-card>.
- Widgets cross-reference: <app-feed-filter>, <app-news-card>.
- Consumers: feed is the office shell default landing.
- Known issues: like/read dispatch on the frontend instead of a
  unified backend endpoint, AdvertCardComponent placement
  algorithm is implicit, FILTER_SPLIT_SYMBOL hardcoded literal,
  FeedItem flattens project/profile/program news under one
  typeModel and reconstructs ownership through contentObject.id.

Mark docs/modules/feed.md as done in docs/PROJECT.md index.

No source changes.
Add docs/modules/chat.md - the most event-heavy module: WS for
realtime + REST for history, with a CQRS-style split into two ports.

- domain/chat: ChatMessage (self-referential replyTo), ChatFile
  (extension TODO: mimetype), ChatItem, the full DTO catalogue
  (Send/Edit/Delete/Read/Typing for commands, OnChatMessage/
  OnEditMessage/OnDeleteMessage/OnReadMessage/TypingInChatEvent/
  OnChangeStatus for events) plus ChatEventType enum
  (new_message, edit_message, delete_message, message_read,
  user_typing, set_online, set_offline).
- Two ports:
  - ChatRepositoryPort (REST: loadMessages, loadProjectFiles,
    hasUnreads).
  - ChatRealtimePort (WS: connect + 5 commands sendMessage/
    editMessage/deleteMessage/readMessage/startTyping + 7 event
    streams onMessage/onEditMessage/onDeleteMessage/onReadMessage/
    onTyping/onSetOnline/onSetOffline). CQRS-style split called
    out as the architectural model.
- 16 use-cases tabulated by REST vs WS-command vs WS-event.
- Facades: ChatInfoService + UI for the directs/groups list,
  ChatDirectInfoService + UI for the per-chat view (subscribes
  to all Observe* use-cases on init), plus the global
  ChatStateService (root) holding unread$ + userOnlineStatusCache
  used by the header badge and online indicators.
- Legacy ChatDirectService / ChatProjectService noted as still
  present alongside the new use-case stack.
- Repositories: ChatRepository (REST pass-through with
  plainToInstance), ChatRealtimeRepository (delegates to
  ChatWsAdapter wrapping core WebsocketService for
  reconnection 5x at environment.websocketReconnectionInterval).
- HTTP endpoints for /messages/*, /messages/files,
  /messages/has_unreads/.
- WS adapter: connects to environment.websocketUrl + "/chat/"
  with Bearer subprotocol, snake_case <-> camelCase via
  WebsocketService, isConnected flag.
- Routes: CHAT_ROUTES (directs/groups + lazy chat-direct),
  CHAT_DIRECT_ROUTES (single chatId).
- Pages: ChatComponent (list), ChatCardComponent (preview),
  ChatDirectComponent (uses <app-chat-window> + <app-message-input>).
- Resolvers ChatResolver / ChatGroupsResolver / ChatDirectResolver.
- Widget cross-reference: app-chat-window + app-message-input.
- Consumers across project-detail/chat, header badge, online
  indicators in info-card/detail, app.component bootstrap.
- Known issues: ChatFile.extension TODO, replyTo unbounded depth,
  legacy services beside use-cases, no toast when WS reconnect
  exhausts, ChatStateService cache not cleared on logout, chatType
  duplicated on every DTO, project query param naming
  inconsistency in loadMessages.

Mark docs/modules/chat.md as done in docs/PROJECT.md index.

No source changes.
…vices

Add docs/modules/office-shell.md covering everything around the
feature modules - the application skeleton.

- OfficeComponent shell:
  - app-office root with side nav + header + profile-control-panel +
    router-outlet, OfficeInfoService bootstraps industries cache,
    chat connect + check unreads, online/offline observers, invite
    accept/reject from the profile dropdown.
  - Page inventory: NavComponent, DeleteConfirmComponent,
    ProgramSidebarCardComponent, SnackbarComponent + AnimationService.
  - OfficeUIInfoService for invites signal and menu state.
  - OfficeResolver loads my invites for the badge.

- Error pages:
  - ErrorComponent layout, ErrorNotFoundComponent (static 404),
    ErrorCodeComponent (dynamic by :code).
  - ERROR_ROUTES with 404 + :code children.
  - OFFICE_ROUTES has ** redirect to /error/404 fallback.
  - Cross-reference back to ErrorService in core lib.

- Onboarding:
  - 4-stage flow (stage-0 base profile + education + workExperience,
    stage-1 specializations, stage-2 skills, stage-3 user type).
  - ONBOARDING_ROUTES with resolvers on stage-1 and stage-2.
  - Per-stage InfoService + UIInfoService facades, plus legacy
    OnboardingService still around.

- UI services in ui/services/:
  - LoadingService - root, BehaviorSubject<boolean> wired into
    <mat-progress-bar> via router events in app.component.
  - SnackbarService - subject of Snack {id, text, timeout, type}
    with success/error/info methods (no warning).
  - NavService - reactive page title via ReplaySubject(1) with
    distinctUntilChanged.
  - NotificationService - present but unused in current code,
    BehaviorSubject<Notification[]> never populated; hasNotifications
    semantics are inverted (counts read, not unread).

- OFFICE_ROUTES walkthrough: lazy onboarding + 9 feature lazy
  loads + members + profile/edit + profile/:id, plus the 404
  fallback. Notes the duplicate /courses and /vacancies entries
  (debt: second block is unreachable) and the commented /chats
  block.

- Consumers: LoadingService used everywhere via app.component,
  SnackbarService for transient feedback, NavService for header
  titles, ChatStateService.unread$ for chat badge.

- Known issues: NotificationService inverted hasNotifications +
  unused, missing warning() in SnackbarService, duplicate
  /courses + /vacancies routes, commented /chats block, legacy
  OnboardingService, oversized stage-0 form, OFFICE_ROUTES sprawl.

Mark docs/modules/office-shell.md as done in docs/PROJECT.md index.

Drop projects/social_platform/src/app/ui/pages/office/README.md and
projects/social_platform/src/app/ui/pages/error/README.md - the
descriptions there reference module structures that moved during
the be9344b refactor; superseded by the new doc.

No source changes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant