Skip to content

feat: feedback service - #95

Merged
hmbanan666 merged 1 commit into
mainfrom
vibrate
Aug 27, 2025
Merged

feat: feedback service#95
hmbanan666 merged 1 commit into
mainfrom
vibrate

Conversation

@hmbanan666

@hmbanan666 hmbanan666 commented Aug 27, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added subtle haptic feedback (vibration) to buttons, switches, navigation, task actions, and avatar tap.
    • Expanded Russian translations for task creation/update and project updates.
  • Style

    • Introduced a muted text color theme variable for consistent styling.
    • Tweaked borders and spacing; simplified UI by removing several tooltips.
  • Refactor

    • Unified feedback handling across the app for consistent vibration behavior.

@hmbanan666 hmbanan666 self-assigned this Aug 27, 2025
@coderabbitai

coderabbitai Bot commented Aug 27, 2025

Copy link
Copy Markdown

Walkthrough

Introduces a shared haptic feedback composable and migrates components to use it for vibration on interactions. Updates UI details in several components, adjusts borders and tooltips, adds a CSS root variable for muted text, modifies the index page avatar flow, and extends Russian locale strings.

Changes

Cohort / File(s) Summary
Haptic feedback migration
apps/atrium-telegram/app/components/*.vue, apps/atrium-telegram/app/pages/index.vue
Replaced direct haptic/toast usages with useFeedback().vibrate in Button, CreateCard, Navigation, TaskCard, TaskList, TasksTodaySwitch, and index page avatar click handler; added/updated event bindings accordingly.
Feedback composable
apps/atrium-telegram/app/composables/useFeedback.ts
Added shared composable exposing vibrate; internally checks haptic availability and triggers light impact if supported.
UI tweaks
apps/atrium-telegram/app/components/CreateCard.vue, .../TaskCard.vue
CreateCard: border-2 → border; UButton receives ui prop for label font. TaskCard: removed tooltip, adjusted border color to secondary/25, removed toast flow, added container click vibrate.
CSS variables
apps/atrium-telegram/app/assets/css/styles.css
Added :root variable --ui-text-muted mapped to var(--tg-theme-hint-color).
Localization
apps/atrium-telegram/i18n/locales/ru-RU.json
Added strings: app.create.task, app.update.task, app.update.task-list with button/title and task completion/close texts.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant C as UI Component
  participant F as useFeedback()
  participant H as hapticFeedback API

  rect rgba(230,245,255,0.6)
    note right of C: On user interaction (click/change)
    User->>C: Trigger event
    C->>F: vibrate()
    alt haptic available
      F->>H: impactOccurred('light')
      H-->>F: ack
    else unavailable
      F-->>C: no-op
    end
  end

  note over C: Continue normal flow (e.g., open modal, navigate)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I tap my paw, a gentle buzz—hooray!
New vibes now ripple through the UI ballet.
Borders slim, tooltips trimmed, we glide,
In Russian whispers, labels ride.
A muted hue, a subtle nudge—so neat!
Hop, vibrate, ship—repeat. 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch vibrate

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@sonarqubecloud

Copy link
Copy Markdown

@hmbanan666
hmbanan666 merged commit d3d360b into main Aug 27, 2025
7 of 8 checks passed
@hmbanan666
hmbanan666 deleted the vibrate branch August 27, 2025 08:54

@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: 3

Caution

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

⚠️ Outside diff range comments (1)
apps/atrium-telegram/app/components/TaskCard.vue (1)

144-164: Type error: DropdownMenuItem doesn’t contain “condition”; build will fail under strict TS

Build the array conditionally instead of attaching a non-existent property.

-const items = computed<DropdownMenuItem[]>(() => {
-  const menuItems: DropdownMenuItem[] = [
-    {
-      label: isFocused.value ? 'Убрать фокус' : 'Сфокусироваться',
-      icon: 'i-lucide-goal',
-      color: 'neutral',
-      disabled: false,
-      onSelect: isFocused.value ? onUnfocus : onFocus,
-      condition: canFocus.value,
-    },
-    {
-      label: 'Редактировать',
-      icon: 'i-lucide-edit',
-      disabled: isCompleted.value,
-      onSelect: () => modalUpdateTask.open({ taskId: task.id }),
-      condition: canEdit.value,
-    },
-  ]
-
-  return menuItems.filter((item) => item.condition)
-})
+const items = computed<DropdownMenuItem[]>(() => {
+  const menuItems: DropdownMenuItem[] = []
+  if (canFocus.value) {
+    menuItems.push({
+      label: isFocused.value ? 'Убрать фокус' : 'Сфокусироваться',
+      icon: 'i-lucide-goal',
+      color: 'neutral',
+      disabled: false,
+      onSelect: isFocused.value ? onUnfocus : onFocus,
+    })
+  }
+  if (canEdit.value) {
+    menuItems.push({
+      label: 'Редактировать',
+      icon: 'i-lucide-edit',
+      disabled: isCompleted.value,
+      onSelect: () => modalUpdateTask.open({ taskId: task.id }),
+    })
+  }
+  return menuItems
+})
🧹 Nitpick comments (8)
apps/atrium-telegram/app/assets/css/styles.css (1)

6-6: Good addition; consider a safe fallback.
Add a fallback to guard against missing theme vars in non-Telegram contexts.

-  --ui-text-muted: var(--tg-theme-hint-color);
+  --ui-text-muted: var(--tg-theme-hint-color, #999999);
apps/atrium-telegram/app/components/TasksTodaySwitch.vue (1)

12-12: Confirm the emitted event name for USwitch.
If USwitch doesn’t emit a native change, prefer the model update event.

-    @change="vibrate"
+    @update:model-value="vibrate"
apps/atrium-telegram/app/components/Navigation.vue (1)

65-68: Avoid redundant navigations.
Skip router.push when already on the target path.

 function handleClick(path: string) {
   vibrate()
-  router.push(path)
+  if (router.currentRoute.value.path !== path) {
+    router.push(path)
+  }
 }
apps/atrium-telegram/app/components/Button.vue (1)

2-5: Set an explicit button type.
Prevents accidental form submission when used inside forms.

-  <button
+  <button
+    type="button"
     class="p-3 tg-bg-button w-full rounded-2xl font-medium cursor-pointer active:scale-95 duration-200"
     @click="vibrate"
   >
apps/atrium-telegram/app/components/CreateCard.vue (1)

10-12: Avoid recreating inline objects on each render

Hoist the ui object to a const (as shown above) to reduce churn and improve readability.

apps/atrium-telegram/app/composables/useFeedback.ts (1)

4-8: Harden for SSR and API availability; allow optional intensity

Guard with import.meta.client and optional chaining to avoid SSR/runtime surprises. Keeping default 'light' preserves current callers.

-function _useFeedback() {
-  function vibrate() {
-    if (hapticFeedback.impactOccurred.isAvailable()) {
-      hapticFeedback.impactOccurred('light')
-    }
-  }
+function _useFeedback() {
+  function vibrate(intensity: 'light' | 'medium' | 'heavy' = 'light') {
+    if (import.meta.client && hapticFeedback?.impactOccurred?.isAvailable?.()) {
+      hapticFeedback.impactOccurred(intensity)
+    }
+  }
apps/atrium-telegram/app/pages/index.vue (1)

43-43: UI spacing change acknowledgement

mb-32 → mb-20 reduces bottom spacing; just ensure it doesn’t cause overlap with any fixed/absolute elements on short viewports.

apps/atrium-telegram/app/components/TaskCard.vue (1)

56-66: Minor: consider haptics on focus/unfocus actions for parity

Optional: call vibrate() inside onFocus/onUnfocus before mutating state to keep feedback consistent across all actions.

Also applies to: 67-70

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 84ea455 and dec7706.

📒 Files selected for processing (10)
  • apps/atrium-telegram/app/assets/css/styles.css (1 hunks)
  • apps/atrium-telegram/app/components/Button.vue (1 hunks)
  • apps/atrium-telegram/app/components/CreateCard.vue (1 hunks)
  • apps/atrium-telegram/app/components/Navigation.vue (2 hunks)
  • apps/atrium-telegram/app/components/TaskCard.vue (4 hunks)
  • apps/atrium-telegram/app/components/TaskList.vue (3 hunks)
  • apps/atrium-telegram/app/components/TasksTodaySwitch.vue (1 hunks)
  • apps/atrium-telegram/app/composables/useFeedback.ts (1 hunks)
  • apps/atrium-telegram/app/pages/index.vue (4 hunks)
  • apps/atrium-telegram/i18n/locales/ru-RU.json (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (10)
apps/atrium-telegram/i18n/locales/ru-RU.json (2)

10-13: New keys look consistent.
Copy reads well and matches existing naming (task vs task-list).


24-33: No English locale present—no parity action needed
The apps/atrium-telegram/i18n/locales directory only contains ru-RU.json; there is no corresponding English JSON to sync against. This service relies on inline/default English strings in code, so adding these keys to another locale file isn’t applicable. If you introduce additional locale files in the future, you’ll want to mirror these keys there.

apps/atrium-telegram/app/components/TasksTodaySwitch.vue (1)

17-17: LGTM on centralized feedback.
Using useFeedback().vibrate keeps haptics consistent.

apps/atrium-telegram/app/components/Navigation.vue (1)

35-35: LGTM: migration to useFeedback.
Centralizing haptics removes repetitive availability checks.

apps/atrium-telegram/app/components/Button.vue (1)

11-11: LGTM on using useFeedback.
Simpler and consistent with the PR-wide pattern.

apps/atrium-telegram/app/components/CreateCard.vue (1)

2-2: Border width change: confirm it aligns with design tokens across cards

Switching from border-2 to border may visually diverge from TaskList and other cards. If uniformity is desired, verify with design.

apps/atrium-telegram/app/pages/index.vue (2)

80-83: LGTM: avatar click now provides haptic feedback before opening the modal

The sequence (vibrate → open) is clear and aligned with the new composable.


51-55: Haptics on CreateCard when clicking outside the button depend on the component

After applying the CreateCard change to emit a click with vibrate from the root, this parent handler will receive the emitted click and users will get consistent haptics across the whole card. Please retest this interaction afterward.

apps/atrium-telegram/app/components/TaskCard.vue (1)

196-206: LGTM: tactile feedback before opening completion modal

The ordering (vibrate → guard → open → reset) reads well and avoids sticky checkbox state.

apps/atrium-telegram/app/components/TaskList.vue (1)

102-103: LGTM: centralized haptics via useFeedback and clean handlers

Handlers are concise and consistent with the PR’s pattern.

Also applies to: 130-138

@@ -1,16 +1,22 @@
<template>
<div class="flex flex-col gap-4 justify-center items-center h-full min-h-40 border-2 border-default border-dashed rounded-lg">
<div class="flex flex-col gap-4 justify-center items-center h-full min-h-40 border border-default border-dashed rounded-lg">

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Emit click from the component and vibrate on the root to ensure consistent haptics across the whole card

Right now, clicking the card background opens the modal (parent @click) but doesn’t vibrate; only the inner button vibrates. Centralize the behavior in CreateCard: vibrate and emit a click from the root, and remove the button-level handler.

Apply within these ranges:

-  <div class="flex flex-col gap-4 justify-center items-center h-full min-h-40 border border-default border-dashed rounded-lg">
+  <div class="flex flex-col gap-4 justify-center items-center h-full min-h-40 border border-default border-dashed rounded-lg" @click="onClick">
       :label="label"
-      :ui="{
-        label: 'font-medium',
-      }"
-      @click="vibrate"
+      :ui="buttonUi"

Add outside the selected ranges in <script setup>:

const emit = defineEmits<{ (e: 'click', ev?: MouseEvent): void }>()
const buttonUi = { label: 'font-medium' }

function onClick(ev?: MouseEvent) {
  vibrate()
  emit('click', ev)
}

Also applies to: 10-14

Comment on lines 56 to 72
<div v-if="canEdit" class="flex flex-row gap-2">
<UTooltip :text="`Редактировать проект «${list?.name}»`">
<UButton
variant="outline"
color="neutral"
size="md"
icon="i-lucide-pencil"
@click="modalUpdateTaskList.open({ listId })"
/>
</UTooltip>
<UButton
variant="outline"
color="neutral"
size="md"
icon="i-lucide-pencil"
@click="handleEditTaskList"
/>

<UTooltip :text="`${$t('app.create.task.button')} в проекте «${list?.name}»`">
<UButton
variant="solid"
color="secondary"
size="md"
icon="i-lucide-plus"
@click="modalCreateTask.open({ performerId: userStore.id, listId })"
/>
</UTooltip>
<UButton
variant="solid"
color="secondary"
size="md"
icon="i-lucide-plus"
@click="handleCreateTask"
/>
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Icon-only buttons need accessible labels

Since tooltips were removed, add aria-label (and optionally title) so screen readers and hover users know the action.

 <UButton
   variant="outline"
   color="neutral"
   size="md"
   icon="i-lucide-pencil"
+  aria-label="Редактировать список"
+  title="Редактировать список"
   @click="handleEditTaskList"
 />
 
 <UButton
   variant="solid"
   color="secondary"
   size="md"
   icon="i-lucide-plus"
+  aria-label="Создать задачу"
+  title="Создать задачу"
   @click="handleCreateTask"
 />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div v-if="canEdit" class="flex flex-row gap-2">
<UTooltip :text="`Редактировать проект «${list?.name`">
<UButton
variant="outline"
color="neutral"
size="md"
icon="i-lucide-pencil"
@click="modalUpdateTaskList.open({ listId })"
/>
</UTooltip>
<UButton
variant="outline"
color="neutral"
size="md"
icon="i-lucide-pencil"
@click="handleEditTaskList"
/>
<UTooltip :text="`${$t('app.create.task.button')} в проекте «${list?.name`">
<UButton
variant="solid"
color="secondary"
size="md"
icon="i-lucide-plus"
@click="modalCreateTask.open({ performerId: userStore.id, listId })"
/>
</UTooltip>
<UButton
variant="solid"
color="secondary"
size="md"
icon="i-lucide-plus"
@click="handleCreateTask"
/>
</div>
<div v-if="canEdit" class="flex flex-row gap-2">
<UButton
variant="outline"
color="neutral"
size="md"
icon="i-lucide-pencil"
aria-label="Редактировать список"
title="Редактировать список"
@click="handleEditTaskList"
/>
<UButton
variant="solid"
color="secondary"
size="md"
icon="i-lucide-plus"
aria-label="Создать задачу"
title="Создать задачу"
@click="handleCreateTask"
/>
</div>
🤖 Prompt for AI Agents
In apps/atrium-telegram/app/components/TaskList.vue around lines 56 to 72, the
icon-only UButton components lack accessible labels; add an aria-label for each
icon-only button (e.g., aria-label="Edit task list" on the pencil button and
aria-label="Create task" on the plus button) and optionally add a matching title
attribute for hover tooltips so screen readers and sighted users can understand
the action.

}
}

export const useFeedback = createSharedComposable(_useFeedback)

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

Missing import: createSharedComposable will be undefined

This will throw at runtime. Import it from @vueuse/core.

+import { createSharedComposable } from '@vueuse/core'
 import { hapticFeedback } from '@telegram-apps/sdk-vue'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const useFeedback = createSharedComposable(_useFeedback)
import { createSharedComposable } from '@vueuse/core'
import { hapticFeedback } from '@telegram-apps/sdk-vue'
export const useFeedback = createSharedComposable(_useFeedback)
🤖 Prompt for AI Agents
In apps/atrium-telegram/app/composables/useFeedback.ts around line 15,
createSharedComposable is used but not imported which will cause a runtime
error; add the import statement "import { createSharedComposable } from
'@vueuse/core'" at the top of the file (with other imports) so
createSharedComposable is defined before exporting useFeedback.

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