Skip to content

feat: weekly mode for charts#42

Merged
hmbanan666 merged 2 commits into
mainfrom
chart-update
Aug 4, 2025
Merged

feat: weekly mode for charts#42
hmbanan666 merged 2 commits into
mainfrom
chart-update

Conversation

@hmbanan666
Copy link
Copy Markdown
Collaborator

@hmbanan666 hmbanan666 commented Aug 4, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a period selection dropdown for choosing daily or weekly data granularity alongside date range pickers on relevant pages.
    • Added localized headers and dynamic page titles for network metrics pages.
  • Enhancements

    • Chart components now support weekly period aggregation, with improved date range handling and formatting for labels and tooltips.
    • Navigation and page elements are now internationalized, supporting dynamic translations.
  • Bug Fixes

    • Improved pluralization and formatting of labels and tooltips in charts for different periods.
  • Documentation

    • Added new Russian translation keys for network metrics.

@hmbanan666 hmbanan666 self-assigned this Aug 4, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Aug 4, 2025

Walkthrough

This update introduces a new PeriodSelect Vue component for selecting data aggregation periods (daily or weekly) based on a chosen date range. Chart components are refactored to support weekly aggregation, using explicit start and end dates for data intervals. Internationalization is improved, with navigation and headers now using translation keys. UI enhancements include flexbox layouts and localized headers.

Changes

Cohort / File(s) Change Summary
Period Selection Component
apps/web-app/app/components/PeriodSelect.vue
Added a new Vue component for selecting period granularity (daily/weekly) based on a date range, with two-way binding and validation logic.
Chart Components: Weekly Aggregation & Formatting
apps/web-app/app/components/chart/KitchenChecks.client.vue, apps/web-app/app/components/chart/KitchenRevenue.client.vue, apps/web-app/app/components/chart/NetworkChecks.client.vue, apps/web-app/app/components/chart/NetworkRevenue.client.vue
Refactored chart data handling to support weekly aggregation with explicit start/end dates, updated label/tooltip formatting, and improved pluralization.
Navigation & Localization
apps/web-app/app/components/Navigation.vue, apps/web-app/i18n/locales/ru-RU.json
Replaced hardcoded Russian navigation label with a translation key; added corresponding translation entry in Russian locale JSON.
Page UI Enhancements
apps/web-app/app/pages/kitchen/[id]/finance.vue, apps/web-app/app/pages/network/index.vue
Updated layouts to use flexbox, added PeriodSelect next to date range pickers, introduced localized headers and dynamic page titles.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Page
    participant PeriodSelect
    participant Chart

    User->>Page: Loads page
    Page->>PeriodSelect: Passes current date range
    PeriodSelect->>User: Renders period dropdown (daily/weekly)
    User->>PeriodSelect: Selects period
    PeriodSelect->>Page: Emits selected period
    Page->>Chart: Passes range and period
    Chart->>Chart: Aggregates data by period (daily/weekly)
    Chart->>User: Displays chart with formatted labels/tooltips
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

Poem

In a warren of charts and hops of time,
A rabbit crafts periods—daily or weekly, sublime.
With labels now local, and headers anew,
The data aligns, as translations grew.
Flex layouts abound, charts aggregate true—
A carrot for progress, and metrics in view! 🥕📊

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chart-update

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.
    • Explain this complex logic.
    • 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. Examples:
    • @coderabbitai explain this code block.
  • 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 src/utils.ts and explain its main purpose.
    • @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 comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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

Documentation and Community

  • 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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (1)
apps/web-app/app/components/PeriodSelect.vue (1)

60-64: Add safety check for edge cases.

The watcher could fail if periods.value is empty or if the first item doesn't have a value property.

 // Ensure the model value is always a valid period
 watch(periods, () => {
-  if (!periods.value.some((p) => p.value === model.value) && periods.value[0]?.value) {
-    model.value = periods.value[0]?.value
+  if (!periods.value.some((p) => p.value === model.value)) {
+    const firstPeriod = periods.value[0]?.value
+    if (firstPeriod) {
+      model.value = firstPeriod
+    }
   }
 })
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ee80625 and a338d31.

📒 Files selected for processing (9)
  • apps/web-app/app/components/Navigation.vue (1 hunks)
  • apps/web-app/app/components/PeriodSelect.vue (1 hunks)
  • apps/web-app/app/components/chart/KitchenChecks.client.vue (5 hunks)
  • apps/web-app/app/components/chart/KitchenRevenue.client.vue (5 hunks)
  • apps/web-app/app/components/chart/NetworkChecks.client.vue (5 hunks)
  • apps/web-app/app/components/chart/NetworkRevenue.client.vue (5 hunks)
  • apps/web-app/app/pages/kitchen/[id]/finance.vue (1 hunks)
  • apps/web-app/app/pages/network/index.vue (3 hunks)
  • apps/web-app/i18n/locales/ru-RU.json (1 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 (11)
apps/web-app/i18n/locales/ru-RU.json (1)

137-139: Good localization practice.

The addition of the network.metrics translation key under the app namespace follows the established i18n structure and enables proper internationalization for the network metrics feature.

apps/web-app/app/components/Navigation.vue (1)

133-133: Excellent internationalization improvement.

Replacing the hardcoded Russian string with the translation key t('app.network.metrics') properly enables localization and maintains consistency with other navigation items.

apps/web-app/app/pages/kitchen/[id]/finance.vue (1)

3-6: Well-integrated period selection feature.

The addition of flexbox styling and the new PeriodSelect component alongside the existing DateRangePicker provides a clean, organized layout for the period selection controls. The two-way binding and prop passing are implemented correctly.

apps/web-app/app/pages/network/index.vue (4)

2-2: Good internationalization of page header.

Adding the localized Header component with the translation key ensures consistent internationalization across the application.


5-8: Consistent UI layout for period controls.

The flexbox styling and PeriodSelect component integration matches the pattern used in the kitchen finance page, providing a consistent user experience across the application.


28-28: Proper setup of internationalization composable.

The useI18n() composable is correctly imported and used for translation functionality.


39-41: Good document head management.

Using useHead with the localized title ensures proper SEO and browser tab title management with internationalization support.

apps/web-app/app/components/PeriodSelect.vue (2)

1-10: Well-structured component template.

The USelect component is properly configured with appropriate styling and two-way binding. The UI configuration for the trailing icon rotation is a nice touch for user experience.


24-57: Smart period selection logic.

The dynamic period options based on date range length provide good UX by limiting choices to meaningful options for different time spans.

apps/web-app/app/components/chart/NetworkChecks.client.vue (1)

150-157: LGTM!

The formatTotalLabel function correctly handles period-aware label formatting with proper Russian pluralization.

apps/web-app/app/components/chart/KitchenChecks.client.vue (1)

147-151: LGTM!

The total calculation correctly filters out zero values and computes the average properly.

Comment thread apps/web-app/app/components/chart/KitchenChecks.client.vue Outdated
Comment thread apps/web-app/app/components/chart/KitchenRevenue.client.vue
Comment thread apps/web-app/app/components/chart/NetworkChecks.client.vue Outdated
Comment on lines +113 to +131

for (const d of allDates) {
// All in one point
const dateStr = format(d, 'yyyy-MM-dd')
const value = values.find((d) => d.date.startsWith(dateStr))

total += value?.total ?? 0
checks += value?.checks ?? 0
averageCheck += value?.averageCheck ?? 0
averageTotal += value?.averageTotal ?? 0
}

points.push({
start: date,
end: dateTo,
total,
checks,
averageCheck: averageCheck / 7,
averageTotal,
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

Fix averaging logic and naming inconsistency.

The weekly aggregation has two issues:

  1. averageCheck calculation assumes all 7 days have data
  2. averageTotal is summed rather than averaged, which seems inconsistent with its name

Apply this diff to fix the issues:

       let total = 0
       let checks = 0
       let averageCheck = 0
       let averageTotal = 0
+      let daysWithData = 0

       for (const d of allDates) {
         // All in one point
         const dateStr = format(d, 'yyyy-MM-dd')
         const value = values.find((d) => d.date.startsWith(dateStr))

         total += value?.total ?? 0
         checks += value?.checks ?? 0
-        averageCheck += value?.averageCheck ?? 0
-        averageTotal += value?.averageTotal ?? 0
+        if (value?.averageCheck) {
+          averageCheck += value.averageCheck
+          daysWithData++
+        }
+        if (value?.averageTotal) {
+          averageTotal += value.averageTotal
+        }
       }

       points.push({
         start: date,
         end: dateTo,
         total,
         checks,
-        averageCheck: averageCheck / 7,
-        averageTotal,
+        averageCheck: daysWithData > 0 ? averageCheck / daysWithData : 0,
+        averageTotal: daysWithData > 0 ? averageTotal / daysWithData : 0,
       })
📝 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
for (const d of allDates) {
// All in one point
const dateStr = format(d, 'yyyy-MM-dd')
const value = values.find((d) => d.date.startsWith(dateStr))
total += value?.total ?? 0
checks += value?.checks ?? 0
averageCheck += value?.averageCheck ?? 0
averageTotal += value?.averageTotal ?? 0
}
points.push({
start: date,
end: dateTo,
total,
checks,
averageCheck: averageCheck / 7,
averageTotal,
let total = 0
let checks = 0
let averageCheck = 0
let averageTotal = 0
+ let daysWithData = 0
for (const d of allDates) {
// All in one point
const dateStr = format(d, 'yyyy-MM-dd')
const value = values.find((d) => d.date.startsWith(dateStr))
total += value?.total ?? 0
checks += value?.checks ?? 0
- averageCheck += value?.averageCheck ?? 0
- averageTotal += value?.averageTotal ?? 0
+ if (value?.averageCheck) {
+ averageCheck += value.averageCheck
+ daysWithData++
+ }
+ if (value?.averageTotal) {
+ averageTotal += value.averageTotal
+ }
}
points.push({
start: date,
end: dateTo,
total,
checks,
- averageCheck: averageCheck / 7,
- averageTotal,
+ averageCheck: daysWithData > 0
+ ? averageCheck / daysWithData
+ : 0,
+ averageTotal: daysWithData > 0
+ ? averageTotal / daysWithData
+ : 0,
})
🤖 Prompt for AI Agents
In apps/web-app/app/components/chart/NetworkRevenue.client.vue around lines 113
to 131, the averaging logic for weekly aggregation is incorrect: averageCheck is
divided by 7 regardless of how many days have data, and averageTotal is summed
instead of averaged. Fix this by counting the number of days with data and
dividing both averageCheck and averageTotal sums by that count to get correct
averages. Also, ensure variable names consistently reflect their purpose.

Comment on lines +28 to +29
label: 'По дням',
value: 'daily',
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

Use internationalization for period labels.

The period labels are hardcoded in Russian, which breaks the internationalization pattern used throughout the application. Consider using translation keys instead.

+const { t } = useI18n()
+
 const periods = computed<{ label: string, value: Period }[]>(() => {
   if (days.value.length <= 14) {
     return [
       {
-        label: 'По дням',
+        label: t('common.period.daily'),
         value: 'daily',
       },
     ]
   }

   if (days.value.length <= 90) {
     return [
       {
-        label: 'По дням',
+        label: t('common.period.daily'),
         value: 'daily',
       },
       {
-        label: 'По неделям',
+        label: t('common.period.weekly'),
         value: 'weekly',
       },
     ]
   }

   return [
     {
-      label: 'По неделям',
+      label: t('common.period.weekly'),
       value: 'weekly',
     },
     // {
-     //   label: 'По месяцам',
+     //   label: t('common.period.monthly'),
     //   value: 'monthly'
     // }
   ]
 })

Don't forget to add the corresponding translation keys to the locale files.

Also applies to: 37-38, 41-42, 49-50

🤖 Prompt for AI Agents
In apps/web-app/app/components/PeriodSelect.vue around lines 28-29 and also
lines 37-38, 41-42, and 49-50, the period labels are hardcoded in Russian, which
breaks the app's internationalization pattern. Replace these hardcoded Russian
strings with translation keys using the app's i18n method (e.g.,
$t('translation.key')). Then add the corresponding translation keys and their
Russian values to the locale files to maintain proper localization support.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Aug 4, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
20.5% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

♻️ Duplicate comments (2)
apps/web-app/app/components/chart/KitchenRevenue.client.vue (1)

111-141: Fix inconsistent aggregation for commonTotal.

The commonTotal is still being summed instead of averaged, which is inconsistent with how averageCheck is handled. This issue was previously raised but only partially addressed.

Apply this diff to fix the averaging:

       let daysWithValues = 0
+      let daysWithMetrics = 0

       let total = 0
       let checks = 0
       let averageCheck = 0
       let commonTotal = 0

       for (const d of allDates) {
         // All in one point
         const dateStr = format(d, 'yyyy-MM-dd')
         const value = values.find((d) => d.date.startsWith(dateStr))
         const metric = metrics.find((d) => d.date.startsWith(dateStr))

         total += value?.total ?? 0
         checks += value?.checks ?? 0
-        commonTotal += metric?.averageTotal ?? 0

         if (value?.averageCheck) {
           averageCheck += value.averageCheck
           daysWithValues++
         }
+
+        if (metric?.averageTotal) {
+          commonTotal += metric.averageTotal
+          daysWithMetrics++
+        }
       }

       points.push({
         start: date,
         end: dateTo,
         total,
         checks,
         averageCheck: daysWithValues > 0 ? averageCheck / daysWithValues : 0,
-        commonTotal,
+        commonTotal: daysWithMetrics > 0 ? commonTotal / daysWithMetrics : 0,
       })
apps/web-app/app/components/chart/NetworkRevenue.client.vue (1)

99-142: Fix inconsistent averaging logic for averageTotal.

While averageCheck is now correctly averaged over days with data, averageTotal is still being summed rather than averaged, which is inconsistent with its name and the past review feedback.

Apply this diff to fix the averaging logic:

       let daysWithValues = 0
+      let daysWithTotalValues = 0

       let total = 0
       let checks = 0
       let averageCheck = 0
       let averageTotal = 0

       for (const d of allDates) {
         // All in one point
         const dateStr = format(d, 'yyyy-MM-dd')
         const value = values.find((d) => d.date.startsWith(dateStr))

         total += value?.total ?? 0
         checks += value?.checks ?? 0
-        averageTotal += value?.averageTotal ?? 0

         if (value?.averageCheck) {
           averageCheck += value.averageCheck
           daysWithValues++
         }
+        if (value?.averageTotal) {
+          averageTotal += value.averageTotal
+          daysWithTotalValues++
+        }
       }

       points.push({
         start: date,
         end: dateTo,
         total,
         checks,
         averageCheck: daysWithValues > 0 ? averageCheck / daysWithValues : 0,
-        averageTotal,
+        averageTotal: daysWithTotalValues > 0 ? averageTotal / daysWithTotalValues : 0,
       })
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a338d31 and ec2aeb0.

📒 Files selected for processing (4)
  • apps/web-app/app/components/chart/KitchenChecks.client.vue (5 hunks)
  • apps/web-app/app/components/chart/KitchenRevenue.client.vue (5 hunks)
  • apps/web-app/app/components/chart/NetworkChecks.client.vue (5 hunks)
  • apps/web-app/app/components/chart/NetworkRevenue.client.vue (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web-app/app/components/chart/NetworkChecks.client.vue
  • apps/web-app/app/components/chart/KitchenChecks.client.vue
⏰ 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 (4)
apps/web-app/app/components/chart/NetworkRevenue.client.vue (4)

55-62: LGTM! Good type design for date ranges.

The updated DataRecord type with start and end dates properly supports the new period-based data aggregation for daily, weekly, and monthly views.


79-79: LGTM! Correct week configuration.

Setting weekStartsOn: 1 (Monday) is appropriate for the weekly aggregation.


83-97: LGTM! Clean daily data processing.

The daily period implementation correctly maps each date to a record with matching start/end dates and handles missing data gracefully with default values.


167-173: LGTM! Well-structured label formatting.

The formatTotalLabel function provides clean period-specific formatting with proper Russian pluralization support.

<div>
<p class="text-xs text-muted uppercase mb-1.5">
Выручка за {{ data.length }} {{ pluralizationRu(data.length, ['день', 'дня', 'дней']) }}
{{ formatTotalLabel('Выручка', data.length) }}
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

Use internationalization for the revenue label.

The hardcoded Russian string 'Выручка' should use a translation key for proper internationalization support, especially since the PR summary mentions improved internationalization.

-          {{ formatTotalLabel('Выручка', data.length) }}
+          {{ formatTotalLabel($t('revenue'), data.length) }}
📝 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
{{ formatTotalLabel('Выручка', data.length) }}
{{ formatTotalLabel($t('revenue'), data.length) }}
🤖 Prompt for AI Agents
In apps/web-app/app/components/chart/KitchenRevenue.client.vue at line 6,
replace the hardcoded Russian string 'Выручка' with a translation key using the
project's internationalization method (e.g., $t or similar). This ensures the
label is properly localized according to the user's language settings. Use the
appropriate translation key instead of the literal string.

monthly: `${formatDate(d.start)} - ${formatDate(d.end)}`,
})[period]

return `<strong>${title}</strong><br> ${d.checks} ${pluralizationRu(d.checks, ['чек', 'чека', 'чеков'])}, средний ${formatNumber(d.averageCheck)}<br> Выручка: ${formatNumber(d.total)}<br> Средняя по сети: ${formatNumber(d.commonTotal)}`
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

Use internationalization for tooltip text.

The tooltip contains hardcoded Russian strings that should use translation keys for consistency with the internationalization improvements mentioned in the PR.

Consider using translation keys for the tooltip text:

  • 'чек/чека/чеков' (check/checks)
  • 'средний' (average)
  • 'Выручка' (Revenue)
  • 'Средняя по сети' (Network average)
🤖 Prompt for AI Agents
In apps/web-app/app/components/chart/KitchenRevenue.client.vue at line 193, the
tooltip text contains hardcoded Russian strings. Replace these hardcoded strings
with appropriate translation keys using the project's internationalization
(i18n) system for 'чек/чека/чеков', 'средний', 'Выручка', and 'Средняя по сети'.
Use the translation function to fetch localized strings and ensure pluralization
is handled via i18n utilities instead of hardcoded plural forms.

<div>
<p class="text-xs text-muted uppercase mb-1.5">
Выручка за {{ data.length }} {{ pluralizationRu(data.length, ['день', 'дня', 'дней']) }}
{{ formatTotalLabel('Выручка', data.length) }}
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

Replace hardcoded Russian text with translation key.

For consistency with the internationalization improvements mentioned in the PR, use a translation key instead of the hardcoded Russian string.

-          {{ formatTotalLabel('Выручка', data.length) }}
+          {{ formatTotalLabel($t('revenue'), data.length) }}
📝 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
{{ formatTotalLabel('Выручка', data.length) }}
{{ formatTotalLabel($t('revenue'), data.length) }}
🤖 Prompt for AI Agents
In apps/web-app/app/components/chart/NetworkRevenue.client.vue at line 6,
replace the hardcoded Russian string 'Выручка' in the formatTotalLabel call with
the appropriate translation key from the i18n setup. This involves importing the
translation function if not already imported, then using it to get the
translated string instead of the hardcoded text to maintain consistency with
internationalization practices.

Comment on lines +183 to +191
function formatTemplate(d: DataRecord) {
const title = ({
daily: `${formatDate(d.start)}, ${format(d.start, 'eeee', { locale: ru })}`,
weekly: `${formatDate(d.start)} - ${formatDate(d.end)}`,
monthly: `${formatDate(d.start)} - ${formatDate(d.end)}`,
})[period]

return `<strong>${title}</strong><br> ${d.checks} ${pluralizationRu(d.checks, ['чек', 'чека', 'чеков'])}, средний ${formatNumber(d.averageCheck)}<br> Выручка: ${formatNumber(d.total)}<br> Средняя у кухни: ${formatNumber(d.averageTotal)}`
}
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

Internationalize hardcoded strings in tooltip template.

The tooltip template contains several hardcoded Russian strings that should use translation keys for consistency with the internationalization improvements.

Consider using translation keys for:

  • "чек/чека/чеков" (checks pluralization)
  • "средний" (average)
  • "Выручка:" (Revenue:)
  • "Средняя у кухни:" (Kitchen average:)

Example:

-  return `<strong>${title}</strong><br> ${d.checks} ${pluralizationRu(d.checks, ['чек', 'чека', 'чеков'])}, средний ${formatNumber(d.averageCheck)}<br> Выручка: ${formatNumber(d.total)}<br> Средняя у кухни: ${formatNumber(d.averageTotal)}`
+  return `<strong>${title}</strong><br> ${d.checks} ${$t('checks', d.checks)}, ${$t('average')} ${formatNumber(d.averageCheck)}<br> ${$t('revenue')}: ${formatNumber(d.total)}<br> ${$t('kitchenAverage')}: ${formatNumber(d.averageTotal)}`
📝 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
function formatTemplate(d: DataRecord) {
const title = ({
daily: `${formatDate(d.start)}, ${format(d.start, 'eeee', { locale: ru })}`,
weekly: `${formatDate(d.start)} - ${formatDate(d.end)}`,
monthly: `${formatDate(d.start)} - ${formatDate(d.end)}`,
})[period]
return `<strong>${title}</strong><br> ${d.checks} ${pluralizationRu(d.checks, ['чек', 'чека', 'чеков'])}, средний ${formatNumber(d.averageCheck)}<br> Выручка: ${formatNumber(d.total)}<br> Средняя у кухни: ${formatNumber(d.averageTotal)}`
}
function formatTemplate(d: DataRecord) {
const title = ({
daily: `${formatDate(d.start)}, ${format(d.start, 'eeee', { locale: ru })}`,
weekly: `${formatDate(d.start)} - ${formatDate(d.end)}`,
monthly: `${formatDate(d.start)} - ${formatDate(d.end)}`,
})[period]
return `<strong>${title}</strong><br> ${d.checks} ${$t('checks', d.checks)}, ${$t('average')} ${formatNumber(d.averageCheck)}<br> ${$t('revenue')}: ${formatNumber(d.total)}<br> ${$t('kitchenAverage')}: ${formatNumber(d.averageTotal)}`
}
🤖 Prompt for AI Agents
In apps/web-app/app/components/chart/NetworkRevenue.client.vue around lines 183
to 191, the tooltip template contains hardcoded Russian strings such as the
plural forms of "чек", "средний", "Выручка:", and "Средняя у кухни:". Replace
these hardcoded strings with appropriate translation keys from the i18n system
to support internationalization. Use the translation function to fetch localized
strings for these labels and ensure the pluralization function also uses
translated forms.

@hmbanan666 hmbanan666 merged commit 0fb64ff into main Aug 4, 2025
7 of 8 checks passed
@hmbanan666 hmbanan666 deleted the chart-update branch August 4, 2025 10:11
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