Skip to content

Уродливая первая версия проекта - #6

Merged
anu-mdl merged 15 commits into
mainfrom
ugly-mvp
May 31, 2026
Merged

Уродливая первая версия проекта#6
anu-mdl merged 15 commits into
mainfrom
ugly-mvp

Conversation

@lukivan8

@lukivan8 lukivan8 commented May 30, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Activities feed displaying local events with timestamps and locations
    • Ability to create new activities with title, location, date/time, and capacity
    • Activity detail view showing cover, description, and participant stats
    • RSVP response system allowing users to register attendance status (going/maybe/can't attend)
    • Activity management interface to edit and cancel events
    • Participant list view for each activity
  • Improvements

    • Enhanced error messages with better clarity
    • Improved data caching and synchronization

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@anu-mdl, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 26 minutes and 27 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 982d4985-f303-411e-93e0-bbbb4a7446f6

📥 Commits

Reviewing files that changed from the base of the PR and between b78225d and c0540ae.

📒 Files selected for processing (9)
  • README.md
  • app/_layout.tsx
  • app/index.tsx
  • docs/core.md
  • docs/quickstart.md
  • src/entities/participant/utils.ts
  • src/features/manage-activity/useManageActivityForm.ts
  • src/features/respond-to-activity/ResponseForm.tsx
  • src/features/respond-to-activity/useRespondedFlag.ts
📝 Walkthrough

Walkthrough

PR introduces a complete activity/event management system into a React Native Expo app, including activities creation and editing, participant response tracking, and participation statistics. Adds comprehensive code quality tooling (Biome, Husky, dependency-cruiser), Russian localization across UI and documentation, and type-safe domain models with Zod validation and React Query caching for all persistent data.

Changes

Activity Management System Implementation

Layer / File(s) Summary
Project Configuration and Documentation
.env.example, AGENTS.md, README.md, nativewind-env.d.ts, CLAUDE.md, TESTS.md, docs/*, app.json
Environment setup with Supabase URL/key directives; Russian localization of agent guidance and README; comprehensive project documentation (architecture principles, git workflow, commands, testing strategy, AI workflow); app manifest adds expo.scheme: "venty" and reformats plugins.
Code Quality and Development Tooling
biome.jsonc, .husky/pre-commit, .husky/pre-push, .dependency-cruiser.cjs, scripts/check-conventions.sh, package.json, babel.config.js
Biome linter and formatter configuration with recommended rules and custom overrides; Husky pre-commit hook runs Biome formatting and convention checks; pre-push hook runs npm run ci; dependency-cruiser enforces FSD layer boundaries; convention checker prevents barrel imports, forbidden styling, and requires type instead of interface; Babel updated to configure NativeWind JSX source; npm scripts add lint, format, test, ci targets; expo-crypto added to dependencies for secure token generation.
Activity Domain Model
src/entities/activity/types.ts, src/entities/activity/schemas.ts, src/entities/activity/utils.ts, src/entities/activity/utils.test.ts
ActivityStatus and Activity types with status, timestamps, and optional fields; Zod validation schemas for create/update forms with capacity coercion and datetime validation; utility functions for slug generation (hyphenated, title-based), edit token generation (UUID), datetime validation and formatting, and status toggling; comprehensive tests covering transformations, edge cases, and Russian date formatting.
Activity API and React Query
src/entities/activity/api.ts, src/entities/activity/hooks.ts, src/entities/activity/mappers.ts, src/entities/activity/mappers.test.ts
Supabase CRUD: list active activities (limit 50), fetch by slug/token, create and update with single-row selection; React Query factory keys and hooks for list/slug/token queries (conditionally enabled); mutations with cache invalidation of list and affected token queries; form-to-input mappers apply date/slug/token transformations and default status to "active"; tests verify null normalization and deterministic token generation.
Participant Domain Model
src/entities/participant/types.ts, src/entities/participant/schemas.ts, src/entities/participant/utils.ts, src/entities/participant/utils.test.ts
ParticipantStatus and Participant types with status, optional telegram/comment, and timestamps; Zod schema requiring name and status, allowing optional telegram/comment; Russian status labels and aggregation utilities to compute per-status counts; tests verify status translation and statistics computation.
Participant API and React Query
src/entities/participant/api.ts, src/entities/participant/hooks.ts, src/entities/participant/mappers.ts, src/entities/participant/mappers.test.ts
Supabase query by activity_id and insert operations; React Query activity-scoped list and mutation hooks with participant-list cache invalidation; form-to-input mapper normalizes optional fields to null; tests verify empty optional field handling.
Shared Infrastructure
src/shared/supabase/client.ts, src/shared/errors/getRussianErrorMessage.ts, src/shared/ui/*, src/shared/lib/*
Supabase client initialized from env vars with AsyncStorage persistence and optional null when unconfigured; Russian error message translation via regex pattern matching for common technical errors; UI components: Button (title-only Pressable), Input/Textarea (FieldShell-wrapped TextInput), Select (button options), DateTimeInput (platform-specific datetime), FormField (Controller wrapper), Page/LoadingPage/ActivityNotFound/BackLink (layout/navigation primitives), ParticipantList (scrollable participant rows), ErrorText (red error display), TextLink (navigation link); helpers for device flag storage, URL building, active element blur, and form server errors.
Root Layout and Navigation
app/_layout.tsx
RootLayout initializes React Query QueryClient and wraps layout in QueryClientProvider; renders simplified Russian header with "Венти" title and two TextLink routes ("Главная" to /, "Создать" to /create); removes prior multi-page navigation system.
Create Activity Feature
app/create.tsx, src/features/create-activity/useCreateActivityForm.ts
CreatePage renders form for activity creation (title, description, city, location, date/time, capacity, cover URL); useCreateActivityForm hook manages form validation, submission (maps to API input, calls mutation, navigates to /manage/${edit_token} on success), and error handling with Russian fallback message.
Activity Detail and Participant Response
app/a/[slug].tsx, src/features/respond-to-activity/ResponseForm.tsx, src/features/respond-to-activity/useRespondToActivityForm.ts, src/features/respond-to-activity/useRespondedFlag.ts
ActivityPage fetches activity/participants via hook and shows loading/not-found states, activity details (cover, title, location, dates, participation stats, cancelled indicator), participant list, and ResponseForm only when activity is active and user has not responded; ResponseForm renders name, telegram, status select, comment textarea, and submit button; useRespondToActivityForm hook manages form initialization, submission with participant creation and response-flag marking; useRespondedFlag hook uses AsyncStorage to track per-device response state.
Activity Management Feature
app/manage/[editToken].tsx, src/features/manage-activity/ManageActivityForm.tsx, src/features/manage-activity/useManageActivityForm.ts
ManagePage routes to edit activity via hook-based state; ManageActivityForm renders editable fields (title, description, city, location, date/time, capacity, cover URL, status select) with save and status-toggle buttons; useManageActivityForm hook loads activity by editToken, initializes form with activity data, implements submit and toggleStatus handlers with mutation-based persistence and Russian error messages, computes publicUrl for sharing.
Home Page with Activity Feed
app/index.tsx
HomePage displays activities feed from useActivities hook with conditional rendering (loading indicator, error message, "no activities" message, or list of activity titles/cities/dates with open links); includes TextLink to create activity page; replaces prior Supabase connectivity check UI.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes


🐰 A hop, skip, and jump through forms so fine,
With Zod and React Query in perfect design,
Participants join, activities flow,
Russian-speaking users now put on a show!
Biome keeps the code tidy and neat,
This PR makes the event app complete! 🎉

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ugly-mvp

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🧹 Nitpick comments (5)
.github/workflows/quality.yml (2)

14-14: ⚖️ Poor tradeoff

Закрепите версии действий по commit SHA для повышения безопасности.

Использование тегов версий (например, @v4) вместо commit SHA делает workflow уязвимым к атакам на цепочку поставок, если тег будет перемещён на вредоносный код.

🔐 Пример закрепления версий
       - name: Забрать код
-        uses: actions/checkout@v4
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

       - name: Настроить Node.js
-        uses: actions/setup-node@v4
+        uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0

Also applies to: 17-17

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/quality.yml at line 14, Replace loose action tags with
pinned commit SHAs: locate the uses statements (e.g., "uses:
actions/checkout@v4" and the other "uses" at the noted line) and change them to
the corresponding actions/checkout@<commit-sha> (and other actions to their
respective repository commit SHAs) so the workflow references exact commit SHAs
instead of floating tags; ensure both occurrences flagged in the comment are
updated and verify the SHAs are the official release commits from the action
repos.

13-14: ⚡ Quick win

Рассмотрите отключение сохранения учётных данных.

По умолчанию actions/checkout сохраняет учётные данные Git, которые могут случайно попасть в артефакты. Рекомендуется явно отключить их для дополнительной безопасности.

🔒 Предлагаемое улучшение безопасности
       - name: Забрать код
         uses: actions/checkout@v4
+        with:
+          persist-credentials: false
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/quality.yml around lines 13 - 14, The checkout step
currently uses actions/checkout@v4 and leaves Git credentials persisted; update
the "Забрать код" step to explicitly disable credential persistence by adding a
with: block that sets persist-credentials: false so credentials are not stored
in the runner or any produced artifacts; keep the step name and uses:
actions/checkout@v4 and only add the with: persist-credentials: false entry.
nativewind-env.d.ts (1)

3-3: 💤 Low value

Комментарий на английском языке.

Файл содержит комментарий на английском языке, что нарушает требование о русском языке для всех .ts файлов. Однако, это автоматически генерируемый файл NativeWind, и изменение его содержимого потребует постобработки или форка библиотеки.

Если требование строгое, можно добавить скрипт постобработки для замены комментария на русский после генерации.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@nativewind-env.d.ts` at line 3, The generated nativewind-env.d.ts contains an
English comment that violates the Russian-only .ts comment policy; since the
file is auto-generated by NativeWind, add a post-generation step (e.g., a
postbuild/postgenerate script invoked after NativeWind runs) that replaces the
English comment with the required Russian text in nativewind-env.d.ts, ensure
this script is referenced in package.json (postbuild/postinstall or a dedicated
script used in CI), and document or automate running it so the committed
generated file always contains the Russian comment instead of the English one.
src/entities/participant/hooks.ts (1)

20-21: ⚡ Quick win

Инвалидируйте список по activity_id из переменных мутации.

Сейчас ключ берется из аргумента хука, а надежнее — из фактического payload мутации.

Предлагаемое изменение
-    onSuccess: () =>
-      qc.invalidateQueries({ queryKey: participantKeys.list(activityId) }),
+    onSuccess: (_data, variables) =>
+      qc.invalidateQueries({
+        queryKey: participantKeys.list(variables.activity_id),
+      }),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/entities/participant/hooks.ts` around lines 20 - 21, The onSuccess
handler currently uses the outer activityId instead of the mutation payload;
update the onSuccess signature to accept the mutation variables (e.g.,
onSuccess: (_data, variables) => ...) and call qc.invalidateQueries({ queryKey:
participantKeys.list(variables.activity_id) }) so the invalidation uses the
actual activity_id from the mutation payload; refer to the onSuccess handler,
participantKeys.list, and qc.invalidateQueries to locate and modify the code.
app/a/[slug].tsx (1)

24-29: 💤 Low value

Duplicate statusText helper.

The same statusText mapping is duplicated in app/manage/[editToken].tsx (lines 26-31). Consider extracting it to a shared module (e.g. under src/entities/participant) so the status→Russian labels stay in sync.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/a/`[slug].tsx around lines 24 - 29, The statusText helper is duplicated;
extract the mapping into a single exported function (e.g., export function
statusText(status: string): string) in a shared module such as
src/entities/participant and replace the local statusText definitions in both
components (the statusText in this file and the one in manage/[editToken].tsx)
with an import from that module; ensure the exported function covers the same
cases ("going", "maybe", "cant" and default) and update imports where used so
both components call the shared statusText.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.env.example:
- Line 4: The line "COPY INTO .env.local" in .env.example is not a valid .env
comment; prefix it with a hash so it becomes a comment (e.g., change the line
represented by the literal "COPY INTO .env.local" to start with "#" so the
parser treats it as a comment and not an invalid environment variable).

In `@app/manage/`[editToken].tsx:
- Around line 58-70: The form reset in the useEffect (the block that calls
reset({...})) runs on every activity change and can clobber unsaved edits when
aq.refetch() is invoked by submit or toggle; change the effect to only
initialize the form once by adding a guard (e.g., a didInit useRef checked in
the effect) so that when activity is first loaded you call reset(...) and set
didInit.current = true, preventing subsequent activity object updates from
resetting the form; apply the same single-initialization guard to the other
reset useEffect referenced around submit/toggle (lines 109-116) so both places
only seed the form on initial load.

In `@src/entities/activity/utils.ts`:
- Around line 1-9: The slugifyTitle function currently uses /[^a-z0-9]+/g which
strips non-ASCII letters (making Cyrillic titles collapse to the "activity"
fallback); update slug generation to allow Unicode letters and numbers by using
a Unicode-aware class (e.g. \p{L} and \p{N}) with the u flag to replace anything
not a letter/number with hyphens, keep the existing .toLowerCase(), trim
surrounding hyphens with the existing replace(/^-+|-+$/g, ""), and keep the
fallback; specifically modify slugifyTitle to use a Unicode regex (and ensure
the regex has the 'u' flag) so Cyrillic and other non-ASCII characters are
preserved in slugs.
- Around line 11-21: The edit token is currently generated with Math.random via
shortRandom(), which is not CSPRNG; replace generateEditToken() to use a
cryptographically secure UUID from expo-crypto (import Crypto from 'expo-crypto'
and call Crypto.randomUUID())—optionally concatenate two UUIDs or strip dashes
for extra length/format—but do not use shortRandom() or Math.random() for bearer
secrets; keep shortRandom() only for non-secret slugs, and update imports/usages
of generateEditToken to reflect the new synchronous CSPRNG function.

In `@src/entities/participant/schemas.ts`:
- Line 4: The name field currently uses z.string().min(1, ...) and therefore
accepts strings of only whitespace; update the participantSchema's name
definition to trim whitespace before validating (e.g., use
z.string().trim().min(1, "Имя обязательно") or an equivalent transform) so
leading/trailing spaces are removed prior to the min(1) check; modify the name
entry in participantSchema accordingly to ensure empty-but-whitespace names are
rejected.

In `@src/shared/ui/Button.tsx`:
- Around line 4-7: The ButtonProps types are too permissive: change title from
ReactNode to string (title?: string) and remove or forbid children in
ButtonProps so non-text nodes can't be passed; then update the Button component
render logic (the Pressable-based Button) to only render <Text>{title}</Text>
and not unconditionally wrap children in <Text>, or alternatively, if you need
children support, keep children but render them outside the <Text> when they are
non-string — adjust the conditional in the Button component that currently does
<Text>{title ?? children}</Text> to handle string title vs non-text children
accordingly.

In `@src/shared/ui/ErrorText.tsx`:
- Around line 5-7: The ErrorText component currently coerces children with
String(children) which turns objects/elements into "[object Object]"; change
ErrorText to accept a normalized text prop (e.g., children?: string | null or
error?: Error | string) or extract a message (e.g., error?.message) and render
that value directly inside <Text className="text-red-700"> without using
String(...); update the component prop types/signature and all callers of
ErrorText (or convert incoming Error props) so only a string (or null) is passed
and displayed.

In `@src/shared/ui/Input.tsx`:
- Around line 4-7: The InputProps type currently defines error as ReactNode but
the component renders it inside <Text>, so narrow the error type to string |
null | undefined in InputProps (replace error?: ReactNode with error?: string |
null | undefined), update any call sites to pass strings (or null/undefined) and
adjust the Input component if it assumes React nodes elsewhere; ensure the
<Text>{error}</Text> usage remains valid and add a short runtime guard (e.g.,
only render <Text> when typeof error === 'string' && error) inside the Input
component if necessary.

In `@src/shared/ui/Textarea.tsx`:
- Line 5: В компоненте Textarea текущее расположение {...props} после явных
атрибутов позволяет входящим пропсам переопределить контракт (multiline,
numberOfLines, textAlignVertical); переместите {...props} перед явными
атрибутами в JSX так, чтобы Input получает сначала все внешние пропсы, а затем
вы жёстко устанавливаете multiline, numberOfLines={4} и textAlignVertical="top"
(отредактируйте строку с <Input .../> в Textarea.tsx).

In `@src/utils/supabase.ts`:
- Around line 9-19: This file currently creates a second Supabase client (using
createClient) which duplicates the instance in the shared supabase client module
and can cause auth/session drift; replace the local createClient usage by
importing and re-exporting the single shared supabase instance (the shared
"supabase" export) instead of constructing a new client here, remove the local
AsyncStorage/config block so configuration lives only in the shared client, and
keep the exported name and nullable typing consistent so callers do not need
changes beyond the import switch.

---

Nitpick comments:
In @.github/workflows/quality.yml:
- Line 14: Replace loose action tags with pinned commit SHAs: locate the uses
statements (e.g., "uses: actions/checkout@v4" and the other "uses" at the noted
line) and change them to the corresponding actions/checkout@<commit-sha> (and
other actions to their respective repository commit SHAs) so the workflow
references exact commit SHAs instead of floating tags; ensure both occurrences
flagged in the comment are updated and verify the SHAs are the official release
commits from the action repos.
- Around line 13-14: The checkout step currently uses actions/checkout@v4 and
leaves Git credentials persisted; update the "Забрать код" step to explicitly
disable credential persistence by adding a with: block that sets
persist-credentials: false so credentials are not stored in the runner or any
produced artifacts; keep the step name and uses: actions/checkout@v4 and only
add the with: persist-credentials: false entry.

In `@app/a/`[slug].tsx:
- Around line 24-29: The statusText helper is duplicated; extract the mapping
into a single exported function (e.g., export function statusText(status:
string): string) in a shared module such as src/entities/participant and replace
the local statusText definitions in both components (the statusText in this file
and the one in manage/[editToken].tsx) with an import from that module; ensure
the exported function covers the same cases ("going", "maybe", "cant" and
default) and update imports where used so both components call the shared
statusText.

In `@nativewind-env.d.ts`:
- Line 3: The generated nativewind-env.d.ts contains an English comment that
violates the Russian-only .ts comment policy; since the file is auto-generated
by NativeWind, add a post-generation step (e.g., a postbuild/postgenerate script
invoked after NativeWind runs) that replaces the English comment with the
required Russian text in nativewind-env.d.ts, ensure this script is referenced
in package.json (postbuild/postinstall or a dedicated script used in CI), and
document or automate running it so the committed generated file always contains
the Russian comment instead of the English one.

In `@src/entities/participant/hooks.ts`:
- Around line 20-21: The onSuccess handler currently uses the outer activityId
instead of the mutation payload; update the onSuccess signature to accept the
mutation variables (e.g., onSuccess: (_data, variables) => ...) and call
qc.invalidateQueries({ queryKey: participantKeys.list(variables.activity_id) })
so the invalidation uses the actual activity_id from the mutation payload; refer
to the onSuccess handler, participantKeys.list, and qc.invalidateQueries to
locate and modify the code.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 188765a8-859c-4419-8ed1-c8836c5334bd

📥 Commits

Reviewing files that changed from the base of the PR and between d48bd77 and 6cc905b.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (34)
  • .env.example
  • .github/workflows/quality.yml
  • .husky/pre-commit
  • .husky/pre-push
  • AGENTS.md
  • README.md
  • app.json
  • app/_layout.tsx
  • app/a/[slug].tsx
  • app/create.tsx
  • app/index.tsx
  • app/manage/[editToken].tsx
  • babel.config.js
  • biome.jsonc
  • nativewind-env.d.ts
  • package.json
  • src/entities/activity/api.ts
  • src/entities/activity/hooks.ts
  • src/entities/activity/schemas.ts
  • src/entities/activity/types.ts
  • src/entities/activity/utils.ts
  • src/entities/participant/api.ts
  • src/entities/participant/hooks.ts
  • src/entities/participant/schemas.ts
  • src/entities/participant/types.ts
  • src/shared/supabase/client.ts
  • src/shared/ui/Button.tsx
  • src/shared/ui/ErrorText.tsx
  • src/shared/ui/Input.tsx
  • src/shared/ui/LoadingText.tsx
  • src/shared/ui/Page.tsx
  • src/shared/ui/Select.tsx
  • src/shared/ui/Textarea.tsx
  • src/utils/supabase.ts

Comment thread .env.example Outdated
Comment thread app/manage/[editToken].tsx Outdated
Comment thread src/entities/activity/utils.ts
Comment thread src/entities/activity/utils.ts Outdated
Comment thread src/entities/participant/schemas.ts Outdated
Comment thread src/shared/ui/Button.tsx
Comment thread src/shared/ui/ErrorText.tsx Outdated
Comment thread src/shared/ui/Input.tsx Outdated
Comment thread src/shared/ui/Textarea.tsx Outdated
Comment thread src/utils/supabase.ts Outdated
@lukivan8

Copy link
Copy Markdown
Member Author

@coderabbitai а можешь на русском описание PR писать?

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown

@lukivan8, конечно! Перегенерирую описание PR на русском языке прямо сейчас.

Пожалуйста, напишите описание на русском языке.


✏️ Learnings added
Learnt from: lukivan8
URL: https://github.com/linkerkz/project-e/pull/6

Timestamp: 2026-05-30T09:49:01.896Z
Learning: For the repository `linkerkz/project-e`, the user `lukivan8` wants all PR descriptions and review summaries to be written in Russian.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

✅ Actions performed

Summary regeneration triggered.

@lukivan8

Copy link
Copy Markdown
Member Author

Превью ветки

https://eproject-preview.ivanlukov.com/

@lukivan8 lukivan8 linked an issue May 30, 2026 that may be closed by this pull request
@lukivan8

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/create.tsx`:
- Line 50: The capacity field is rendered with field("capacity", ...) which
passes a string from onChangeText into the form, so ensure the
CreateActivityForm schema coerces/preprocesses capacity to a number (e.g., use
z.coerce.number() or a preprocess that casts empty -> null or string -> number)
so runtime submissions send a number/null instead of a string; update the
CreateActivityForm schema (capacity property) accordingly and keep
validation/nullable semantics consistent with tests.

In `@src/entities/activity/utils.test.ts`:
- Around line 47-52: The test for toDateTimeLocalInputValue depends on the
runtime timezone because the implementation uses local getters
(getFullYear/getHours/getMinutes); make the test deterministic by computing the
expected string from the same Date logic instead of hardcoding it (e.g., build
expected = new Date(input) and call its local getters to format
"YYYY-MM-DDTHH:MM"), or alternatively set the test environment TZ to UTC; update
the test case that uses toDateTimeLocalInputValue("2006-02-01T06:22:00+00:00")
to compute the expected value from new Date(value) using the same local getters
so it passes in any timezone.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1b0f927a-de3e-49cc-a937-6d91473f2292

📥 Commits

Reviewing files that changed from the base of the PR and between 6cc905b and 4e80c53.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (32)
  • .env.example
  • .github/workflows/quality.yml
  • TESTS.md
  • app/_layout.tsx
  • app/a/[slug].tsx
  • app/create.tsx
  • app/index.tsx
  • app/manage/[editToken].tsx
  • package.json
  • src/entities/activity/mappers.test.ts
  • src/entities/activity/mappers.ts
  • src/entities/activity/schemas.ts
  • src/entities/activity/utils.test.ts
  • src/entities/activity/utils.ts
  • src/entities/participant/hooks.ts
  • src/entities/participant/mappers.test.ts
  • src/entities/participant/mappers.ts
  • src/entities/participant/schemas.ts
  • src/entities/participant/utils.test.ts
  • src/entities/participant/utils.ts
  • src/features/create-activity/useCreateActivityForm.ts
  • src/features/manage-activity/useManageActivityForm.ts
  • src/features/respond-to-activity/useActivityResponseForm.ts
  • src/shared/errors/getRussianErrorMessage.test.ts
  • src/shared/errors/getRussianErrorMessage.ts
  • src/shared/lib/blurActiveElement.ts
  • src/shared/ui/Button.tsx
  • src/shared/ui/DateTimeInput.tsx
  • src/shared/ui/ErrorText.tsx
  • src/shared/ui/Input.tsx
  • src/shared/ui/Textarea.tsx
  • src/utils/supabase.ts
✅ Files skipped from review due to trivial changes (5)
  • src/shared/lib/blurActiveElement.ts
  • src/shared/errors/getRussianErrorMessage.ts
  • TESTS.md
  • src/entities/participant/utils.ts
  • .env.example
🚧 Files skipped from review as they are similar to previous changes (8)
  • package.json
  • .github/workflows/quality.yml
  • src/entities/participant/schemas.ts
  • src/entities/participant/hooks.ts
  • src/shared/ui/Textarea.tsx
  • app/index.tsx
  • src/entities/activity/schemas.ts
  • app/_layout.tsx

Comment thread app/create.tsx Outdated
Comment thread src/entities/activity/utils.test.ts
@lukivan8 lukivan8 assigned lukivan8 and anu-mdl and unassigned anu-mdl May 30, 2026
@lukivan8
lukivan8 requested a review from anu-mdl May 30, 2026 10:44
anu-mdl and others added 7 commits May 31, 2026 13:41
depcruise + npm run arch стерегут направление импортов FSD, pre-commit гоняет grep-проверки core.md. Плюс scheme для deep links и nativewind jsxImportSource.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
core/commands/git_workflow/about_the_project/ai_workflow + ссылки из CLAUDE.md. TESTS.md синхронизирован с тестами.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…abase

Поля формы собраны вокруг FieldShell (Input/Select/DateTimeInput), добавлены FormField, ErrorText через getRussianErrorMessage, ActivityNotFound/LoadingPage/ParticipantList/Back/TextLink. Вынесены buildActivityPublicUrl/setFormServerError/storage. Удалён мёртвый src/utils/supabase и isSupabaseConfigured.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ResponseForm/ManageActivityForm + хуки useRespondToActivityForm/useRespondedFlag заменили useActivityResponseForm. Формы используют setFormServerError.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/ai_workflow.md (1)

1-95: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Сделайте документ полностью русскоязычным.

Сейчас есть англоязычные фрагменты (например, на Line 1 и в терминах внутри текста: trade-offs, edge cases, best practices, boilerplate). Для .md в этом репозитории требуется русский язык для всего содержимого.

As per coding guidelines **/*.{js,jsx,ts,tsx,md,json}: All content, comments, and documentation must be in Russian language.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/ai_workflow.md` around lines 1 - 95, Документ содержит англоязычные
фрагменты (заголовок "AI-Assisted Development Workflow" и терминология в тексте:
"trade-offs", "edge cases", "best practices", "boilerplate" и т.п. внутри
backticks); исправьте это, переведя весь файл на русский — включая заголовки,
все маркеры в тексте и термины в инлайновом коде — и замените англоязычные
выражения на корректные русские эквиваленты (например, "AI-Assisted Development
Workflow" → "Рабочий процесс с поддержкой ИИ", "trade-offs" → "компромиссы",
"edge cases" → "крайние случаи/особые сценарии", "best practices" → "лучшие
практики", "boilerplate" → "шаблонный код"), убедитесь, что ни одно слово в
кодовых блоках/инлайновых кавычках не остаётся на английском и соблюдайте
требования локализации для всех секций (Исследование, Обсуждение, План,
Реализация, Ревью, Генерация тестов и принцип).
🧹 Nitpick comments (2)
app/index.tsx (1)

27-30: 💤 Low value

Предпочтительнее общий форматтер даты вместо toLocaleString()

new Date(activity.starts_at).toLocaleString() без явного locale/options будет давать разный формат на разных устройствах/платформах (и уже используется в app/index.tsx и app/a/[slug].tsx). В src/entities/activity/utils.ts есть только toIsoDate и toDateTimeLocalInputValue (конвертация), поэтому для отображения стоит завести общий formatter и переиспользовать его в обоих местах.

<Text>
  {activity.title}{activity.city}{" "}
  {new Date(activity.starts_at).toLocaleString()}
</Text>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/index.tsx` around lines 27 - 30, The code uses new
Date(activity.starts_at).toLocaleString() in UI components (app/index.tsx and
app/a/[slug].tsx) causing inconsistent formats; add a shared formatter in
src/entities/activity/utils.ts (e.g., export function formatActivityDate(date:
string | Date): string or formatDateTime) that accepts a Date/string and returns
a consistently formatted string using a chosen locale and options, export it,
then replace the inline new Date(...).toLocaleString() calls in the components
with formatActivityDate(activity.starts_at) (or the chosen function name) so
both places reuse the same deterministic formatter.
src/shared/ui/DateTimeInput.tsx (1)

15-33: 💤 Low value

Web branch silently drops ...props (asymmetric with native branch).

The native branch forwards {...props} to Input, but the web <input> does not. No current caller passes extra props, so there's no live bug, but the divergence is a footgun if a prop like autoComplete/maxLength is later added.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/shared/ui/DateTimeInput.tsx` around lines 15 - 33, The web branch of
DateTimeInput drops additional props (asymmetric with the native branch that
forwards {...props} to Input); update the web JSX input element to forward the
same incoming props as the native branch by spreading the component props (e.g.,
...props) onto the <input> while preserving explicit attributes like id/name
(using nativeID conversion) and existing handlers (value, onChange) so extra
props such as autoComplete or maxLength are not lost; ensure this mirrors the
behavior of the native branch that passes {...props} to Input.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/git_workflow.md`:
- Around line 5-9: The fenced code blocks in git_workflow.md (the examples
showing the branch/PR diagram and the later code block around lines 82-87) are
missing a language tag which triggers markdownlint MD040; update each
triple-backtick fence to include an appropriate language identifier such as text
or bash (e.g., ```text or ```bash) for the blocks that contain plain
command/diagram output so the linter is satisfied and syntax highlighting is
clearer.
- Line 1: Заголовок "Git Workflow" нужно перевести на русский: замените строку с
заголовком (текущий текст "Git Workflow") на корректный русский вариант,
например "Рабочий процесс Git" (и убедитесь, что весь остальной контент в этом
файле — docs/git_workflow.md — тоже приведён к русскому языку и сохранён в
UTF-8).

In `@src/entities/participant/utils.ts`:
- Around line 23-24: The type guard isParticipantStatus currently uses the
unsafe `in` operator which can return true for prototype properties (e.g.,
"toString"), producing false positives; replace that check with an own-property
check against participantStatusLabels (for example, using
Object.prototype.hasOwnProperty.call(participantStatusLabels, status) or
checking Object.keys(participantStatusLabels).includes(status as string)) so the
guard only returns true for actual keys of participantStatusLabels and not
inherited properties. Ensure the function signature (isParticipantStatus(status:
string): status is ParticipantStatus) remains the same and update any related
tests if needed.

In `@src/features/manage-activity/useManageActivityForm.ts`:
- Around line 54-69: toggleStatus currently optimistically sets
form.setValue("status", next) before calling mutation.mutateAsync but does not
restore the prior value on failure; capture the previous status
(activity.status) into a local variable before calling form.setValue, and in the
catch block call form.setValue("status", previous) to revert the optimistic
change, then call setFormServerError(form.setError, "Не удалось изменить статус
активности", error) as already done; update the toggleStatus function to use
these symbols (toggleStatus, form.setValue, mutation.mutateAsync,
activity.status, setFormServerError) so a failed toggle leaves the form status
consistent with persisted activity.

In `@src/features/respond-to-activity/ResponseForm.tsx`:
- Around line 56-59: The submit Button remains pressable while saving; update
the Button in ResponseForm to pass disabled={isSaving} so the Pressable
forwarded prop from src/shared/ui/Button.tsx is set and prevents double
submissions; locate the Button usage that currently has title={isSaving ?
"Сохраняем..." : "Отправить отклик"} and add disabled={isSaving}, ensuring this
ties to the same isSaving state returned by useRespondToActivityForm (which
wraps handleSubmit(onSubmit) and triggers mutation.mutateAsync before
markResponded()).

In `@src/shared/lib/storage.ts`:
- Around line 5-12: Wrap AsyncStorage calls in readDeviceFlag and
writeDeviceFlag with try/catch: in readDeviceFlag (function readDeviceFlag)
catch any error from AsyncStorage.getItem and return false (treat as "not
responded"); in writeDeviceFlag (function writeDeviceFlag) catch errors from
AsyncStorage.setItem and either log the error (using console.warn or existing
logger) or silently swallow it so callers like markResponded don't throw—ensure
both functions keep their same signatures and only return/resolve safe fallback
values on failure.

---

Outside diff comments:
In `@docs/ai_workflow.md`:
- Around line 1-95: Документ содержит англоязычные фрагменты (заголовок
"AI-Assisted Development Workflow" и терминология в тексте: "trade-offs", "edge
cases", "best practices", "boilerplate" и т.п. внутри backticks); исправьте это,
переведя весь файл на русский — включая заголовки, все маркеры в тексте и
термины в инлайновом коде — и замените англоязычные выражения на корректные
русские эквиваленты (например, "AI-Assisted Development Workflow" → "Рабочий
процесс с поддержкой ИИ", "trade-offs" → "компромиссы", "edge cases" → "крайние
случаи/особые сценарии", "best practices" → "лучшие практики", "boilerplate" →
"шаблонный код"), убедитесь, что ни одно слово в кодовых блоках/инлайновых
кавычках не остаётся на английском и соблюдайте требования локализации для всех
секций (Исследование, Обсуждение, План, Реализация, Ревью, Генерация тестов и
принцип).

---

Nitpick comments:
In `@app/index.tsx`:
- Around line 27-30: The code uses new Date(activity.starts_at).toLocaleString()
in UI components (app/index.tsx and app/a/[slug].tsx) causing inconsistent
formats; add a shared formatter in src/entities/activity/utils.ts (e.g., export
function formatActivityDate(date: string | Date): string or formatDateTime) that
accepts a Date/string and returns a consistently formatted string using a chosen
locale and options, export it, then replace the inline new
Date(...).toLocaleString() calls in the components with
formatActivityDate(activity.starts_at) (or the chosen function name) so both
places reuse the same deterministic formatter.

In `@src/shared/ui/DateTimeInput.tsx`:
- Around line 15-33: The web branch of DateTimeInput drops additional props
(asymmetric with the native branch that forwards {...props} to Input); update
the web JSX input element to forward the same incoming props as the native
branch by spreading the component props (e.g., ...props) onto the <input> while
preserving explicit attributes like id/name (using nativeID conversion) and
existing handlers (value, onChange) so extra props such as autoComplete or
maxLength are not lost; ensure this mirrors the behavior of the native branch
that passes {...props} to Input.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 67ccefa1-c71d-40be-9c3f-8658ec8482c8

📥 Commits

Reviewing files that changed from the base of the PR and between 4e80c53 and b78225d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (51)
  • .dependency-cruiser.cjs
  • .gitignore
  • .husky/pre-commit
  • CLAUDE.md
  • TESTS.md
  • app.json
  • app/_layout.tsx
  • app/a/[slug].tsx
  • app/create.tsx
  • app/index.tsx
  • app/manage/[editToken].tsx
  • babel.config.js
  • biome.jsonc
  • docs/about_the_project.md
  • docs/ai_workflow.md
  • docs/commands.md
  • docs/core.md
  • docs/git_workflow.md
  • package.json
  • scripts/check-conventions.sh
  • src/entities/activity/hooks.ts
  • src/entities/activity/mappers.test.ts
  • src/entities/activity/mappers.ts
  • src/entities/activity/schemas.ts
  • src/entities/activity/utils.test.ts
  • src/entities/activity/utils.ts
  • src/entities/participant/hooks.ts
  • src/entities/participant/utils.test.ts
  • src/entities/participant/utils.ts
  • src/features/create-activity/useCreateActivityForm.ts
  • src/features/manage-activity/ManageActivityForm.tsx
  • src/features/manage-activity/useManageActivityForm.ts
  • src/features/respond-to-activity/ResponseForm.tsx
  • src/features/respond-to-activity/useRespondToActivityForm.ts
  • src/features/respond-to-activity/useRespondedFlag.ts
  • src/shared/lib/buildActivityPublicUrl.ts
  • src/shared/lib/setFormServerError.ts
  • src/shared/lib/storage.ts
  • src/shared/supabase/client.ts
  • src/shared/ui/ActivityNotFound.tsx
  • src/shared/ui/BackLink.tsx
  • src/shared/ui/DateTimeInput.tsx
  • src/shared/ui/ErrorText.tsx
  • src/shared/ui/FieldShell.tsx
  • src/shared/ui/FormField.tsx
  • src/shared/ui/Input.tsx
  • src/shared/ui/LoadingPage.tsx
  • src/shared/ui/ParticipantList.tsx
  • src/shared/ui/Select.tsx
  • src/shared/ui/TextLink.tsx
  • src/utils/supabase.ts
💤 Files with no reviewable changes (2)
  • src/shared/supabase/client.ts
  • src/utils/supabase.ts
✅ Files skipped from review due to trivial changes (8)
  • src/shared/ui/LoadingPage.tsx
  • src/shared/ui/BackLink.tsx
  • src/shared/lib/buildActivityPublicUrl.ts
  • .gitignore
  • docs/commands.md
  • docs/about_the_project.md
  • CLAUDE.md
  • TESTS.md
🚧 Files skipped from review as they are similar to previous changes (9)
  • src/shared/ui/Input.tsx
  • src/entities/activity/mappers.test.ts
  • src/shared/ui/Select.tsx
  • .husky/pre-commit
  • src/entities/activity/hooks.ts
  • biome.jsonc
  • package.json
  • src/entities/activity/schemas.ts
  • src/entities/activity/utils.test.ts

Comment thread docs/git_workflow.md
@@ -0,0 +1,89 @@
# Git Workflow

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Переведите заголовок на русский.

На Line 1 заголовок Git Workflow выбивается из русскоязычного стандарта документации проекта.

As per coding guidelines **/*.{js,jsx,ts,tsx,md,json}: All content, comments, and documentation must be in Russian language.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/git_workflow.md` at line 1, Заголовок "Git Workflow" нужно перевести на
русский: замените строку с заголовком (текущий текст "Git Workflow") на
корректный русский вариант, например "Рабочий процесс Git" (и убедитесь, что
весь остальной контент в этом файле — docs/git_workflow.md — тоже приведён к
русскому языку и сохранён в UTF-8).

Comment thread docs/git_workflow.md
Comment on lines +5 to +9
```
main
↑ PR (issue-28/add-map → main)
issue-28/add-map
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Добавьте язык у fenced code blocks.

На Line 5 и Line 82 блоки кода без указания языка — это ловит markdownlint (MD040). Добавьте, например, text/bash там, где уместно.

Also applies to: 82-87

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 5-5: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/git_workflow.md` around lines 5 - 9, The fenced code blocks in
git_workflow.md (the examples showing the branch/PR diagram and the later code
block around lines 82-87) are missing a language tag which triggers markdownlint
MD040; update each triple-backtick fence to include an appropriate language
identifier such as text or bash (e.g., ```text or ```bash) for the blocks that
contain plain command/diagram output so the linter is satisfied and syntax
highlighting is clearer.

Comment thread src/entities/participant/utils.ts Outdated
Comment thread src/features/manage-activity/useManageActivityForm.ts
Comment thread src/features/respond-to-activity/ResponseForm.tsx
Comment thread src/shared/lib/storage.ts
anu-mdl and others added 4 commits May 31, 2026 14:18
in ловит ключи прототипа (toString и пр.) — type guard давал ложный true. Object.hasOwn проверяет только собственные ключи словаря.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
AsyncStorage обёрнут в обработку ошибок (некритичный флаг не роняет отклик), submit-кнопка отклика блокируется на isSaving (нет дублей), оптимистичный статус откатывается при сбое мутации.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Заголовки в UI и упоминание в core.md приведены к латинскому Venty.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@anu-mdl
anu-mdl merged commit 5d4b49a into main May 31, 2026
1 of 2 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jun 28, 2026
This was referenced Jul 7, 2026
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.

Сделать "craigslist" версию проекта

2 participants