From 292597e7c6f1a4d3a435ed1132a12c77027e43f5 Mon Sep 17 00:00:00 2001 From: Mohamad Tarbin Date: Sun, 16 Aug 2026 11:52:40 -0400 Subject: [PATCH 1/3] ran npm run lint:fix --- e2e/debug.mjs | 4 +- e2e/fixtures/auth.js | 9 +- e2e/global-setup.js | 10 +- e2e/tests/auth.spec.js | 14 +- src/components/NotificationTemplate.jsx | 5 +- src/components/SSEConnectionStatus.jsx | 5 +- src/components/SSESettings.jsx | 9 +- src/components/SubscriptionModal.jsx | 17 ++- src/components/UserProfileAvatar.jsx | 11 +- src/components/animations/AnimatedList.jsx | 45 ++++--- src/components/animations/LoadingScreen.jsx | 10 +- src/components/animations/PageTransition.jsx | 3 +- src/components/animations/SkeletonLoader.jsx | 4 +- src/components/animations/SmoothCard.jsx | 31 ++--- src/components/animations/StaggeredList.jsx | 9 +- src/components/common/AppModal.jsx | 20 +-- src/components/common/DurationInput.jsx | 5 +- src/components/common/EmptyState.jsx | 10 +- src/components/common/FilterBar.jsx | 15 ++- .../common/KeyboardShortcutHint.jsx | 6 +- src/components/common/ModalActions.jsx | 4 +- .../common/filter/ActiveFilterChips.jsx | 1 - src/contexts/QueryContext.jsx | 1 + src/contexts/SSEContext.jsx | 1 + src/hooks/NetworkManager.jsx | 1 + src/hooks/useAcknowledgmentModal.js | 2 +- src/hooks/useAnimations.js | 8 +- src/hooks/useAuth.jsx | 1 + src/hooks/useConfirmationModal.js | 2 +- src/hooks/useDescriptionHtml.js | 1 + src/hooks/useDocumentScanner.js | 19 ++- src/hooks/useFileUpload.js | 2 +- src/hooks/usePendingCommands.js | 1 + src/hooks/useResponsiveModal.js | 1 + src/hooks/useSSE.js | 3 +- src/hooks/useSSEContext.js | 1 + src/queries/ResourceQueries.jsx | 3 +- src/queries/SubtaskQueries.jsx | 1 + src/queries/ThingQueries.jsx | 1 + src/queries/TimeQueries.jsx | 3 +- src/service/AIPromptCache.js | 20 ++- src/service/LocalAIService.js | 23 +++- src/service/NFCWriter.jsx | 7 +- src/service/VoiceInputService.js | 25 ++-- src/service/WidgetService.js | 1 + src/utils/ChoreCardHelpers.jsx | 18 ++- src/utils/Chores.jsx | 3 +- src/utils/DateFormatter.js | 6 +- src/utils/Fetcher.jsx | 12 +- src/utils/FilterEngine.js | 4 +- src/utils/ImageCache.js | 2 +- src/utils/OfflineDB.js | 13 +- src/utils/SyncEngine.js | 6 +- src/utils/UserHelpers.js | 26 ++-- src/views/Authorization/AuthFields.jsx | 9 +- src/views/Authorization/AuthShell.jsx | 7 +- src/views/Authorization/Authenticating.jsx | 10 +- .../Authorization/ForgotPasswordView.jsx | 1 + src/views/Authorization/LoginSettings.jsx | 16 +-- src/views/Authorization/LoginView.jsx | 4 +- .../Authorization/MFAVerificationModal.jsx | 19 ++- src/views/Authorization/Signup.jsx | 3 +- src/views/ChoreEdit/ChoreView.jsx | 16 +-- src/views/ChoreEdit/ThingTriggerSection.jsx | 10 +- src/views/ChoreEdit/TimePassedCard.jsx | 1 + src/views/ChoreEdit/TimerSplitButton.jsx | 8 +- src/views/Chores/ActivitesCard.jsx | 3 +- src/views/Chores/ArchivedTasks.jsx | 5 +- src/views/Chores/ChoreListView.jsx | 34 ++--- src/views/Chores/CompactChoreCard.jsx | 15 ++- src/views/Chores/IconButtonWithMenu.jsx | 13 +- .../Chores/LocalNotificationScheduler.js | 2 +- src/views/Chores/MultiSelectHelp.jsx | 5 +- src/views/Chores/MyChores.jsx | 6 +- .../Chores/NotificationAccessSnackbar.jsx | 1 + src/views/Chores/Sidepanel.jsx | 5 +- src/views/Chores/SmartInsightsCard.jsx | 5 +- src/views/Chores/SortAndGrouping.jsx | 19 +-- src/views/Chores/TasksByAssigneeCard.jsx | 3 +- src/views/Chores/UserSwitcher.jsx | 12 +- src/views/Chores/components/ChoreModals.jsx | 13 +- .../components/ChoreToolbarPrototype.jsx | 85 ++++++------ .../Chores/components/CustomFilterChips.jsx | 18 ++- .../components/FilterBuilderContent.jsx | 43 ++++--- src/views/Chores/components/FilterSection.jsx | 7 +- .../Chores/components/MultiSelectToolbar.jsx | 21 +-- src/views/Chores/components/MyChoreHeader.jsx | 3 +- src/views/Chores/hooks/useChoreActions.js | 33 ++--- src/views/Chores/hooks/useChoreModals.js | 2 +- src/views/ChoresOverview.jsx | 2 +- src/views/Error.jsx | 5 +- src/views/Filters/FilterView.jsx | 2 +- src/views/History/ChoreHistory.jsx | 18 +-- src/views/History/HistoryCard.jsx | 121 +++++++++++++----- src/views/Home.jsx | 4 +- src/views/Labels/LabelQueries.jsx | 1 + src/views/Landing/DemoCalendar.jsx | 1 + .../Landing/DemoNotificationTemplate.jsx | 1 + src/views/Landing/Footer.jsx | 5 +- src/views/Landing/GettingStarted.jsx | 2 +- src/views/Landing/HomeHero.jsx | 6 +- src/views/Landing/Landing.jsx | 4 +- .../Landing/TabletInstallationSection.jsx | 3 +- .../Modals/Inputs/AcknowledgmentModal.jsx | 1 + .../Modals/Inputs/AdvancedFilterBuilder.jsx | 15 ++- .../Modals/Inputs/AttachmentBrowserModal.jsx | 6 +- .../Modals/Inputs/AttachmentViewerModal.jsx | 5 +- .../Modals/Inputs/BackupRestoreModal.jsx | 6 +- src/views/Modals/Inputs/ConfirmationModal.jsx | 1 + .../Modals/Inputs/CreateChildUserModal.jsx | 3 +- src/views/Modals/Inputs/CreateThingModal.jsx | 7 +- src/views/Modals/Inputs/DateModal.jsx | 7 +- src/views/Modals/Inputs/EditThingState.jsx | 7 +- src/views/Modals/Inputs/IconPickerModal.jsx | 9 +- src/views/Modals/Inputs/LabelModal.jsx | 8 +- .../Inputs/NativeCancelSubscriptionModal.jsx | 1 + src/views/Modals/Inputs/NoteViewerModal.jsx | 1 + src/views/Modals/Inputs/NudgeModal.jsx | 1 + .../Modals/Inputs/PasswordChangeModal.jsx | 8 +- src/views/Modals/Inputs/ProjectModal.jsx | 3 +- src/views/Modals/Inputs/SelectModal.jsx | 5 +- src/views/Modals/Inputs/TextModal.jsx | 11 +- src/views/Modals/Inputs/TimerEditModal.jsx | 8 +- src/views/Modals/Inputs/UserDeletionModal.jsx | 5 +- src/views/Modals/Inputs/UserModal.jsx | 7 +- src/views/Modals/Inputs/WriteNFCModal.jsx | 15 ++- src/views/Modals/RedeemPointsModal.jsx | 6 +- src/views/Onboarding/GetStartedView.jsx | 1 + src/views/Onboarding/OnboardingVignettes.jsx | 47 +++---- src/views/Onboarding/WorkspaceReadyView.jsx | 5 +- src/views/Payments/PaymentFailView.jsx | 3 +- src/views/Payments/PaymentSuccessView.jsx | 3 +- src/views/Settings/ProfileSettings.jsx | 3 +- src/views/Settings/Settings.jsx | 9 +- src/views/Settings/SettingsLayout.jsx | 2 +- src/views/Settings/SettingsRoutes.jsx | 2 +- src/views/Settings/ThemeToggle.jsx | 3 +- src/views/Settings/ThemeToggleButton.jsx | 3 +- src/views/TestView/TimerCard.jsx | 11 +- src/views/Things/ThingsHistory.jsx | 11 +- src/views/Timer/TimerDetails.jsx | 11 +- src/views/User/UserActivities.jsx | 77 +++++++---- src/views/User/UserPoints.jsx | 27 ++-- .../components/AdvancedOptionsSection.jsx | 39 +++--- src/views/components/AutocompleteInput.jsx | 4 +- src/views/components/AutocompleteSelect.jsx | 2 +- src/views/components/BaseOptionPicker.jsx | 32 ++--- src/views/components/CalendarCard.jsx | 10 +- src/views/components/CalendarDual.jsx | 9 +- src/views/components/CalendarMonthly.jsx | 7 +- src/views/components/ChoreActionMenu.jsx | 36 ++++-- src/views/components/DueDatePickerField.jsx | 7 +- src/views/components/DueDatePickerModal.jsx | 11 +- src/views/components/IconButtonTouchable.jsx | 2 +- src/views/components/LabelsPickerField.jsx | 9 +- src/views/components/Loading.jsx | 3 +- src/views/components/NavBarLink.jsx | 2 +- src/views/components/NavBarMobile.jsx | 16 +-- src/views/components/NotFound.jsx | 1 + .../components/NotificationPickerField.jsx | 12 +- src/views/components/PendingBadge.jsx | 3 +- src/views/components/PhotoTaskModal.jsx | 9 +- src/views/components/PriorityPickerField.jsx | 9 +- src/views/components/ProjectPickerField.jsx | 7 +- src/views/components/ProjectSelector.jsx | 17 ++- src/views/components/RepeatPickerField.jsx | 13 +- src/views/components/RichTextEditor.jsx | 27 ++-- src/views/components/ScanToTask/ScanPanel.jsx | 8 +- .../components/ScanToTask/useScanToTask.js | 12 +- src/views/components/SmartTaskTitleInput.jsx | 18 +-- src/views/components/SubTask.jsx | 19 +-- src/views/components/SyncStatusIndicator.jsx | 7 +- .../components/VoiceToTask/VoicePanel.jsx | 34 ++--- .../components/VoiceToTask/parseVoiceTask.js | 13 +- .../components/VoiceToTask/useVoiceToTask.js | 8 +- vite.config.mjs | 1 + 176 files changed, 1101 insertions(+), 767 deletions(-) diff --git a/e2e/debug.mjs b/e2e/debug.mjs index c575e8f..a278f09 100644 --- a/e2e/debug.mjs +++ b/e2e/debug.mjs @@ -6,7 +6,9 @@ const browser = await chromium.launch() const context = await browser.newContext({ storageState: state }) const page = await context.newPage() page.on('console', msg => console.log('[console]', msg.type(), msg.text())) -page.on('pageerror', err => console.log('[pageerror]', err.message, '\n', err.stack)) +page.on('pageerror', err => + console.log('[pageerror]', err.message, '\n', err.stack), +) await page.goto('http://localhost:5173/chores/create') await page.getByTestId('chore-name-input').fill('Debug Chore ' + Date.now()) diff --git a/e2e/fixtures/auth.js b/e2e/fixtures/auth.js index 06b1747..33369f4 100644 --- a/e2e/fixtures/auth.js +++ b/e2e/fixtures/auth.js @@ -1,4 +1,4 @@ -import { test as base, expect } from '@playwright/test' +import { expect, test as base } from '@playwright/test' import path from 'path' import { fileURLToPath } from 'url' @@ -9,7 +9,10 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)) * After successful signup the app auto-logs in and walks through the * onboarding flow (/circle-setup, then /ready) before landing on /chores. */ -export async function signUpViaUI(page, { username, email, password, displayName }) { +export async function signUpViaUI( + page, + { displayName, email, password, username }, +) { await page.goto('/signup') await page.locator('#username').fill(username) await page.locator('#email').fill(email) @@ -30,7 +33,7 @@ export async function signUpViaUI(page, { username, email, password, displayName * Fill and submit the login form through the UI. * After successful login the app redirects to /chores. */ -export async function loginViaUI(page, { username, password }) { +export async function loginViaUI(page, { password, username }) { await page.goto('/login') await page.locator('#username').fill(username) await page.locator('#password').fill(password) diff --git a/e2e/global-setup.js b/e2e/global-setup.js index 1d949d9..e509587 100644 --- a/e2e/global-setup.js +++ b/e2e/global-setup.js @@ -1,4 +1,4 @@ -import { writeFile, mkdir } from 'fs/promises' +import { mkdir, writeFile } from 'fs/promises' import path from 'path' import { fileURLToPath } from 'url' @@ -56,7 +56,7 @@ export default async function globalSetup() { throw new Error(`Login failed (${loginRes.status}): ${body}`) } - const { token, expire } = await loginRes.json() + const { expire, token } = await loginRes.json() // Write a Playwright storage-state file containing the token in localStorage const stateDir = path.join(__dirname, '.auth') @@ -84,7 +84,11 @@ export default async function globalSetup() { async function waitForServer(url, retries = 20, delayMs = 1000) { for (let i = 0; i < retries; i++) { try { - const res = await fetch(`${url}/api/v1/auth/login`, { method: 'POST', body: '{}', headers: { 'Content-Type': 'application/json' } }) + const res = await fetch(`${url}/api/v1/auth/login`, { + method: 'POST', + body: '{}', + headers: { 'Content-Type': 'application/json' }, + }) if (res.status < 500) return } catch { // server not up yet diff --git a/e2e/tests/auth.spec.js b/e2e/tests/auth.spec.js index 9c049a7..508e0a3 100644 --- a/e2e/tests/auth.spec.js +++ b/e2e/tests/auth.spec.js @@ -1,12 +1,14 @@ -import { test, expect } from '@playwright/test' -import { signUpViaUI, loginViaUI } from '../fixtures/auth.js' +import { expect, test } from '@playwright/test' + +import { loginViaUI, signUpViaUI } from '../fixtures/auth.js' // Username must match /^[a-z.-]+$/ — no digits allowed. // Generate a random lowercase-only suffix for uniqueness across runs. function randomSuffix(len = 8) { const chars = 'abcdefghijklmnopqrstuvwxyz' - return Array.from({ length: len }, () => - chars[Math.floor(Math.random() * 26)], + return Array.from( + { length: len }, + () => chars[Math.floor(Math.random() * 26)], ).join('') } @@ -41,7 +43,9 @@ test.describe('Auth – Sign Up', () => { test.describe('Auth – Login', () => { // Re-use the shared E2E user that global-setup already created - test('logs in with valid credentials and lands on /chores', async ({ page }) => { + test('logs in with valid credentials and lands on /chores', async ({ + page, + }) => { await loginViaUI(page, { username: 'e2e.user', password: 'E2ePassword123!', diff --git a/src/components/NotificationTemplate.jsx b/src/components/NotificationTemplate.jsx index d942681..2db2d90 100644 --- a/src/components/NotificationTemplate.jsx +++ b/src/components/NotificationTemplate.jsx @@ -14,6 +14,7 @@ import Select from '@mui/joy/Select' import Typography from '@mui/joy/Typography' import { useCallback, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' + import { NOTIFICATION_TYPE, TASK_COLOR } from '../utils/Colors' import { TIME_UNITS } from '../utils/DurationUtils' @@ -26,7 +27,7 @@ const timingOptions = [ ] function getRelativeLabel(notification, t) { - const { value, unit } = notification + const { unit, value } = notification const numericValue = Number(value) if (numericValue === 0) { return t('notifTemplate.onDueDate') @@ -71,8 +72,8 @@ const NotificationTemplate = ({ // Consumers that own an empty state themselves pass 0. minNotifications = 1, onChange, - value, showTimeline = true, + value, }) => { const { t } = useTranslation('chores') const [notifications, setNotifications] = useState( diff --git a/src/components/SSEConnectionStatus.jsx b/src/components/SSEConnectionStatus.jsx index 718d355..df7b744 100644 --- a/src/components/SSEConnectionStatus.jsx +++ b/src/components/SSEConnectionStatus.jsx @@ -1,13 +1,14 @@ import { Circle, SignalWifi4Bar, SignalWifiOff } from '@mui/icons-material' import { Box, Chip, Tooltip, Typography } from '@mui/joy' + import { useSSEContext } from '../hooks/useSSEContext' const SSEConnectionStatus = ({ - variant = 'minimal', showError = false, sx = {}, + variant = 'minimal', }) => { - const { isConnected, isConnecting, error, getConnectionStatus } = + const { error, getConnectionStatus, isConnected, isConnecting } = useSSEContext() const getStatusColor = () => { diff --git a/src/components/SSESettings.jsx b/src/components/SSESettings.jsx index 3187bdc..679206d 100644 --- a/src/components/SSESettings.jsx +++ b/src/components/SSESettings.jsx @@ -9,22 +9,23 @@ import { Switch, Typography, } from '@mui/joy' +import { useTranslation } from 'react-i18next' + import { useSSEContext } from '../hooks/useSSEContext' import { useUserProfile } from '../queries/UserQueries' import { isPlusAccount } from '../utils/Helpers' import SSEConnectionStatus from './SSEConnectionStatus' -import { useTranslation } from 'react-i18next' const SSESettings = () => { const { t } = useTranslation('settings') const { data: userProfile } = useUserProfile() const { - isConnected, - isConnecting, error, getConnectionStatus, - toggleSSEEnabled, + isConnected, + isConnecting, isSSEEnabled, + toggleSSEEnabled, } = useSSEContext() const handleToggle = () => { diff --git a/src/components/SubscriptionModal.jsx b/src/components/SubscriptionModal.jsx index e5fe314..c4079f4 100644 --- a/src/components/SubscriptionModal.jsx +++ b/src/components/SubscriptionModal.jsx @@ -1,13 +1,14 @@ import { Check, Star } from '@mui/icons-material' import { Box, Card, Chip, Divider, Radio, Typography } from '@mui/joy' import { useState } from 'react' -import AppModal from './common/AppModal' -import ModalActions from './common/ModalActions' -import { useNotification } from '../service/NotificationProvider' -import { GetSubscriptionSession } from '../utils/Fetcher' import { useTranslation } from 'react-i18next' -const SubscriptionModal = ({ open, onClose }) => { +import { useNotification } from '../service/NotificationProvider' +import { GetSubscriptionSession } from '../utils/Fetcher' +import AppModal from './common/AppModal' +import ModalActions from './common/ModalActions' + +const SubscriptionModal = ({ onClose, open }) => { const { t } = useTranslation('settings') const [selectedPlan, setSelectedPlan] = useState('yearly') const [isLoading, setIsLoading] = useState(false) @@ -81,7 +82,11 @@ const SubscriptionModal = ({ open, onClose }) => { footer={ { const { t } = useTranslation('common') @@ -43,11 +44,11 @@ const UserProfileAvatar = () => { const { mode, setMode } = useColorScheme() const { data: userProfile } = useUserProfile() const { + canImpersonate, + getEffectiveUser, isImpersonating, startImpersonation, stopImpersonation, - canImpersonate, - getEffectiveUser, } = useImpersonateUser() const { data: circleMembersData } = useCircleMembers() const [isModalOpen, setIsModalOpen] = useState(false) @@ -129,7 +130,9 @@ const UserProfileAvatar = () => { }} /> { // Handle both children and items patterns let childrenArray if (items && renderItem) { - childrenArray = items.map((item, index) => - React.cloneElement(renderItem(item, index), { - key: keyExtractor ? keyExtractor(item, index) : index - }) + childrenArray = items.map((item, index) => + React.cloneElement(renderItem(item, index), { + key: keyExtractor ? keyExtractor(item, index) : index, + }), ) } else { childrenArray = React.Children.toArray(children) } - + const visibleItems = useStaggeredAnimation(childrenArray.length, staggerDelay) const prefersReducedMotion = useReducedMotion() // If user prefers reduced motion, render without animations if (prefersReducedMotion) { return ( - - {items && renderItem ? childrenArray : children} - + {items && renderItem ? childrenArray : children} ) } @@ -55,7 +58,7 @@ const AnimatedList = ({ {childrenArray.map((child, index) => { const isVisible = visibleItems.has(index) - + return ( { +const LoadingScreen = ({ message = null, showLogo = true, size = 'lg' }) => { const { t } = useTranslation('common') return ( @@ -90,7 +86,7 @@ const LoadingScreen = ({ )} - + - + {message ?? t('loading')} diff --git a/src/components/animations/PageTransition.jsx b/src/components/animations/PageTransition.jsx index bff11ed..cb51333 100644 --- a/src/components/animations/PageTransition.jsx +++ b/src/components/animations/PageTransition.jsx @@ -1,7 +1,8 @@ +import './PageTransition.css' + import { useLayoutEffect, useRef, useState } from 'react' import { flushSync } from 'react-dom' import { useLocation } from 'react-router-dom' -import './PageTransition.css' // Route hierarchy for determining navigation direction const routeHierarchy = { diff --git a/src/components/animations/SkeletonLoader.jsx b/src/components/animations/SkeletonLoader.jsx index 244bddf..af2095f 100644 --- a/src/components/animations/SkeletonLoader.jsx +++ b/src/components/animations/SkeletonLoader.jsx @@ -1,11 +1,11 @@ import { Box, Skeleton } from '@mui/joy' const SkeletonLoader = ({ - type = 'card', count = 1, height = 100, - width = '100%', + type = 'card', variant = 'rectangular', + width = '100%', ...props }) => { const renderSkeleton = () => { diff --git a/src/components/animations/SmoothCard.jsx b/src/components/animations/SmoothCard.jsx index 9d26f1e..839b072 100644 --- a/src/components/animations/SmoothCard.jsx +++ b/src/components/animations/SmoothCard.jsx @@ -1,23 +1,23 @@ -import React from 'react' import { Card } from '@mui/joy' import { styled } from '@mui/joy/styles' +import React from 'react' const AnimatedCard = styled(Card)(({ theme }) => ({ transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)', transform: 'translateZ(0)', // Enable GPU acceleration cursor: 'pointer', position: 'relative', - + '&:hover': { transform: 'translateY(-4px) translateZ(0)', boxShadow: theme.shadow.lg, }, - + '&:active': { transform: 'translateY(-2px) translateZ(0)', transition: 'all 0.1s cubic-bezier(0.4, 0, 0.2, 1)', }, - + // Subtle background animation on hover '&::before': { content: '""', @@ -26,49 +26,50 @@ const AnimatedCard = styled(Card)(({ theme }) => ({ left: 0, right: 0, bottom: 0, - background: 'linear-gradient(45deg, transparent, rgba(255,255,255,0.1), transparent)', + background: + 'linear-gradient(45deg, transparent, rgba(255,255,255,0.1), transparent)', opacity: 0, transition: 'opacity 0.3s ease', pointerEvents: 'none', borderRadius: 'inherit', }, - + '&:hover::before': { opacity: 1, }, - + // Focus states for accessibility '&:focus-visible': { outline: '2px solid', outlineColor: theme.palette.primary[500], outlineOffset: '2px', }, - + // Reduced motion support '@media (prefers-reduced-motion: reduce)': { transition: 'none', transform: 'none !important', - + '&:hover': { transform: 'none', boxShadow: theme.shadow.md, // Still provide visual feedback }, - + '&:active': { transform: 'none', }, - + '&::before': { display: 'none', }, }, })) -const SmoothCard = ({ - children, - onClick, +const SmoothCard = ({ animationDisabled = false, - ...props + children, + onClick, + ...props }) => { if (animationDisabled) { return ( diff --git a/src/components/animations/StaggeredList.jsx b/src/components/animations/StaggeredList.jsx index 32970c5..96a139e 100644 --- a/src/components/animations/StaggeredList.jsx +++ b/src/components/animations/StaggeredList.jsx @@ -1,13 +1,14 @@ +import './PageTransition.css' + import { Box } from '@mui/joy' import React, { useEffect, useState } from 'react' import { CSSTransition, TransitionGroup } from 'react-transition-group' -import './PageTransition.css' const StaggeredList = ({ - children, - staggerDelay = 50, - initialDelay = 0, animate = true, + children, + initialDelay = 0, + staggerDelay = 50, }) => { const [isVisible, setIsVisible] = useState(!animate) diff --git a/src/components/common/AppModal.jsx b/src/components/common/AppModal.jsx index 84b1677..228bba5 100644 --- a/src/components/common/AppModal.jsx +++ b/src/components/common/AppModal.jsx @@ -17,27 +17,27 @@ const WIDTH_BY_SIZE = { const AppModal = forwardRef( ( { - open, - onClose, + backdropBlur = true, children, - title, + closeOnBackdrop = true, + closeOnEscape = true, + contentSx, description, footer, - size = 'md', + footerSx, fullWidth = true, isMobile: isMobileProp, keepMounted = false, + maxHeight = '90dvh', mobilePresentation = 'sheet', + onClose, + open, role = 'dialog', showCloseButton = true, showHandle = false, - closeOnBackdrop = true, - closeOnEscape = true, - backdropBlur = true, - maxHeight = '90dvh', - contentSx, - footerSx, + size = 'md', sx, + title, unmountDelay = 180, ...modalProps }, diff --git a/src/components/common/DurationInput.jsx b/src/components/common/DurationInput.jsx index a1bac5f..91ece5d 100644 --- a/src/components/common/DurationInput.jsx +++ b/src/components/common/DurationInput.jsx @@ -1,6 +1,7 @@ import { Add, Remove } from '@mui/icons-material' import { Box, IconButton, Input, Option, Select } from '@mui/joy' import { useEffect, useState } from 'react' + import { secondsToValueAndUnit, TIME_UNITS, @@ -16,7 +17,7 @@ import { * size – Joy UI size ('sm' | 'md') * minValue – minimum numeric value (default 1) */ -const DurationInput = ({ value, onChange, size = 'md', minValue = 1 }) => { +const DurationInput = ({ minValue = 1, onChange, size = 'md', value }) => { const derived = value != null && value >= 0 ? secondsToValueAndUnit(value) @@ -26,7 +27,7 @@ const DurationInput = ({ value, onChange, size = 'md', minValue = 1 }) => { useEffect(() => { if (value != null && value >= 0) { - const { value: v, unit: u } = secondsToValueAndUnit(value) + const { unit: u, value: v } = secondsToValueAndUnit(value) setDisplayValue(v) setUnit(u) } diff --git a/src/components/common/EmptyState.jsx b/src/components/common/EmptyState.jsx index 95250fd..b02bf2e 100644 --- a/src/components/common/EmptyState.jsx +++ b/src/components/common/EmptyState.jsx @@ -55,7 +55,7 @@ const SIZES = { } const ActionButton = ({ action, ...buttonProps }) => { - const { label, to, onClick, ...rest } = action + const { label, onClick, to, ...rest } = action return ( ) -export const SocialButton = ({ icon, children, sx, ...props }) => ( +export const SocialButton = ({ children, icon, sx, ...props }) => (