Skip to content
Open

Dev #47

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
ad59697
feat: pwa
dkcodec Feb 3, 2026
01669f9
feat: pwa
dkcodec Feb 3, 2026
538c451
Merge pull request #38 from dkcodec/pwa
dkcodec Feb 3, 2026
24838b9
feat: PWA + notifictaion
dkcodec Feb 4, 2026
20ebed1
upd: refresh to main page
dkcodec Feb 6, 2026
ffba374
Merge pull request #39 from dkcodec/pwa
dkcodec Feb 6, 2026
bac0f9f
feat: schedule
dkcodec Feb 24, 2026
db9cb25
prettier
dkcodec Feb 24, 2026
080a296
update: new endpoints, new logic
dkcodec Mar 10, 2026
ccb3cc0
pettier: -fix
dkcodec Mar 10, 2026
3706818
Merge pull request #40 from dkcodec/ref/newFlow
dkcodec Mar 10, 2026
18800c2
empty
dkcodec Mar 10, 2026
b0a543c
Merge pull request #41 from dkcodec/ref/newFlow
dkcodec Mar 10, 2026
57fdd20
upd: staff search
dkcodec Mar 14, 2026
fe3042c
Merge branch 'upd/schedule' of https://github.com/dkcodec/app-bagsy i…
dkcodec Mar 14, 2026
94797e6
upd: schedule
dkcodec Mar 30, 2026
75508b6
format
dkcodec Mar 30, 2026
c4cbdee
feat: account page
dkcodec Mar 31, 2026
642b676
fix: popular
dkcodec Mar 31, 2026
f04cb2c
feat: locations, cubscription
dkcodec Mar 31, 2026
e5c6527
upd: schedule
dkcodec Mar 31, 2026
7fffc39
format
dkcodec Mar 31, 2026
05bab86
upd: style
dkcodec Mar 31, 2026
138744b
upd: organization, activation for point
dkcodec Mar 31, 2026
95a5aed
upd: docs
dkcodec Mar 31, 2026
bfb8906
upd: docs
dkcodec Mar 31, 2026
5b2d981
feat: schedule for locations in network
dkcodec Mar 31, 2026
8b2584c
format
dkcodec Mar 31, 2026
d791d1c
upd: service
dkcodec Mar 31, 2026
fff70e5
move: master-service to employees-service
dkcodec Mar 31, 2026
a41e436
udp: staff
dkcodec Apr 1, 2026
490e5a1
udp: service to vault bottom sheet
dkcodec Apr 1, 2026
c1fbd76
udp: close app-sidebar
dkcodec Apr 1, 2026
0b83a7a
add: staff docs
dkcodec Apr 1, 2026
5a645de
format
dkcodec Apr 1, 2026
581d95f
fix: logout cache
dkcodec Apr 1, 2026
8e6b31c
upd: calendar
dkcodec Apr 1, 2026
de893c8
upd: calendar url, rm: refs, useless loaders
dkcodec Apr 1, 2026
151fc51
feat: color to service seelct
dkcodec Apr 1, 2026
6792154
feat: select sidebar location
dkcodec Apr 1, 2026
7502727
upd: memo schedule
dkcodec Apr 1, 2026
5ecc7bc
upd: memo schedule
dkcodec Apr 1, 2026
b5bee87
fix: localization for add event modal
dkcodec Apr 1, 2026
b9fbc36
fix: localization for add event modal
dkcodec Apr 1, 2026
2ae364f
upd: deps
dkcodec Apr 1, 2026
30573d2
feat: unlink service, unlink location
dkcodec Apr 2, 2026
0b2e504
feat: unlink service, unlink location
dkcodec Apr 2, 2026
d5abf52
feat: unlink service, unlink location
dkcodec Apr 2, 2026
336890a
feat: global location select for services
dkcodec Apr 2, 2026
61c6e30
upd: collapsed sidebar
dkcodec Apr 2, 2026
fdec943
upd: sidebar styles
dkcodec Apr 2, 2026
0f32db2
upd: menu hover color
dkcodec Apr 2, 2026
64ab2a9
fix: logout clear persist
dkcodec Apr 2, 2026
6e247ff
upd: logo
dkcodec Apr 2, 2026
3d75155
upd: logo
dkcodec Apr 2, 2026
cb689c7
upd: auth in-memory reset
dkcodec Apr 2, 2026
268966b
udp: current event
dkcodec Apr 2, 2026
94c29ec
Merge pull request #42 from dkcodec/ref/newFlow
dkcodec Apr 2, 2026
650f7a3
fix: schedule
dkcodec Apr 2, 2026
08c060f
Merge pull request #43 from dkcodec/fix/schedule
dkcodec Apr 2, 2026
d16a4b6
fix: schedule
dkcodec Apr 5, 2026
095244b
fix: disabled hours
dkcodec Apr 5, 2026
8e2e99f
fix: schedule
dkcodec Apr 5, 2026
cc255d0
fix: schecdule when removed, saved days
dkcodec Apr 5, 2026
d3b1461
upd: detach only for network
dkcodec Apr 5, 2026
e43c386
feat: showing if unlinked master of service for add-event
dkcodec Apr 5, 2026
9a8f0b2
Merge pull request #44 from dkcodec/fix/schedule
dkcodec Apr 5, 2026
4863dea
fix: service staff map
dkcodec Apr 5, 2026
cac06ce
Merge pull request #45 from dkcodec/fix/schedule
dkcodec Apr 5, 2026
c84408b
feat: staff service view
dkcodec Apr 5, 2026
836816c
Merge pull request #46 from dkcodec/fix/schedule
dkcodec Apr 6, 2026
def8191
fix: schedule for tofay
dkcodec Apr 7, 2026
f876e29
Merge pull request #48 from dkcodec/fix/schedule
dkcodec Apr 7, 2026
e64182d
fix: toast
dkcodec May 16, 2026
aa846f6
Merge pull request #49 from dkcodec/fix/translations
dkcodec May 16, 2026
5c8c82a
feat: analytics
dkcodec Jun 9, 2026
f03fbcb
feat: error handlers
dkcodec Jun 9, 2026
7a11d31
fix: login redirect
dkcodec Jun 9, 2026
5d91876
Merge pull request #50 from dkcodec/feat/analytics
dkcodec Jun 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"permissions": {
"allow": ["mcp__acp__Edit"]
"allow": ["mcp__acp__Edit", "Bash(npx next build)"]
}
}
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ yarn-error.log*
# vercel
.vercel

# Serwist (PWA)
/public/sw.js
/public/sw.js.map
/public/swe-worker-*.js
/public/swe-worker-*.js.map
/public/workbox-*.js
/public/workbox-*.js.map
/public/serialized-*.js
/public/serialized-*.js.map

# typescript
*.tsbuildinfo
next-env.d.ts

certificates
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,11 @@ You can check out [the Next.js GitHub repository](https://github.com/vercel/next
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

## PWA

Приложение настроено как PWA (manifest, Serwist, офлайн-страница, иконки).

- **Проверка:** Chrome DevTools → Application → Manifest, Service Workers.
- **Lighthouse:** запустить аудит PWA и Performance по HTTPS (`next build` + `next start` или деплой).
- **Локально с HTTPS:** `next dev --experimental-https` для тестов установки и push (если позже добавите).
2 changes: 1 addition & 1 deletion app/[locale]/(auth)/invite/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default async function InvitePage({
let tokenData;
try {
tokenData = await AuthService.verifyAuthToken(token);
} catch (error) {
} catch {
// Если токен невалиден (401) или произошла ошибка - показываем not-found
notFound();
}
Expand Down
10 changes: 10 additions & 0 deletions app/[locale]/(sidebar)/account/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"use client";

import { AccountPage } from "@/src/features/account";

/**
* Страница аккаунта — объединяет профиль, подписку, безопасность, настройки
*/
export default function Page() {
return <AccountPage />;
}
20 changes: 20 additions & 0 deletions app/[locale]/(sidebar)/analytics/clients/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Suspense } from "react";
import { Loader } from "lucide-react";
import { AnalyticsClients, AnalyticsGuard } from "@/src/features/analytics";

/** /analytics/clients — раздел "Клиенты" (Beta). Manager/Owner. */
export default function AnalyticsClientsPage() {
return (
<Suspense
fallback={
<div className="flex items-center justify-center min-h-[40vh]">
<Loader className="size-6 animate-spin text-muted-foreground" />
</div>
}
>
<AnalyticsGuard requires="clients">
<AnalyticsClients />
</AnalyticsGuard>
</Suspense>
);
}
20 changes: 20 additions & 0 deletions app/[locale]/(sidebar)/analytics/finance/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Suspense } from "react";
import { Loader } from "lucide-react";
import { AnalyticsFinance, AnalyticsGuard } from "@/src/features/analytics";

/** /analytics/finance — финансовый отчёт. Manager/Owner. */
export default function AnalyticsFinancePage() {
return (
<Suspense
fallback={
<div className="flex items-center justify-center min-h-[40vh]">
<Loader className="size-6 animate-spin text-muted-foreground" />
</div>
}
>
<AnalyticsGuard requires="finance">
<AnalyticsFinance />
</AnalyticsGuard>
</Suspense>
);
}
28 changes: 28 additions & 0 deletions app/[locale]/(sidebar)/analytics/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"use client";
import { usePathname } from "next/navigation";
import { AnalyticsHeader } from "@/src/features/analytics";

/**
* Layout раздела аналитики.
* - Рендерит общую шапку (title + табы + period picker).
* - Каждый подэкран при смене pathname получает свежий ключ → плавный re-mount
* через tailwindcss-animate (fade + slide). prefers-reduced-motion → мгновенно.
*/
export default function AnalyticsLayout({
children,
}: {
children: React.ReactNode;
}) {
const pathname = usePathname();
return (
<>
<AnalyticsHeader />
<div
key={pathname}
className="motion-safe:animate-in motion-safe:fade-in motion-safe:slide-in-from-bottom-2 motion-safe:duration-300"
>
{children}
</div>
</>
);
}
28 changes: 28 additions & 0 deletions app/[locale]/(sidebar)/analytics/locations/[locationId]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Suspense } from "react";
import { Loader } from "lucide-react";
import { AnalyticsGuard, LocationDetail } from "@/src/features/analytics";

/**
* /analytics/locations/[locationId] — drill-down по локации.
* Доступ только Network Owner (guard "locations").
*/
export default async function LocationAnalyticsPage({
params,
}: {
params: Promise<{ locationId: string }>;
}) {
const { locationId } = await params;
return (
<Suspense
fallback={
<div className="flex items-center justify-center min-h-[40vh]">
<Loader className="size-6 animate-spin text-muted-foreground" />
</div>
}
>
<AnalyticsGuard requires="locations">
<LocationDetail locationId={locationId} />
</AnalyticsGuard>
</Suspense>
);
}
20 changes: 20 additions & 0 deletions app/[locale]/(sidebar)/analytics/me/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Suspense } from "react";
import { Loader } from "lucide-react";
import { AnalyticsGuard, AnalyticsMe } from "@/src/features/analytics";

/** /analytics/me — личная аналитика; доступно всем ролям. */
export default function AnalyticsMePage() {
return (
<Suspense
fallback={
<div className="flex items-center justify-center min-h-[40vh]">
<Loader className="size-6 animate-spin text-muted-foreground" />
</div>
}
>
<AnalyticsGuard requires="me">
<AnalyticsMe />
</AnalyticsGuard>
</Suspense>
);
}
45 changes: 45 additions & 0 deletions app/[locale]/(sidebar)/analytics/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"use client";
import { Suspense, useEffect } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { Loader } from "lucide-react";
import {
AnalyticsGuard,
AnalyticsOverview,
getAnalyticsAccess,
} from "@/src/features/analytics";
import { useCurrentUser } from "@/src/shared/hooks/use-users";

/**
* /analytics — корневой роут.
* Smart redirect:
* - Staff и Solo Owner → /analytics/me
* - остальные → рендерится Overview
*/
export default function AnalyticsRootPage() {
const router = useRouter();
const searchParams = useSearchParams();
const { data: user, isLoading } = useCurrentUser();

useEffect(() => {
if (isLoading || !user) return;
const access = getAnalyticsAccess(user);
if (access.defaultTab === "me") {
const qs = searchParams.toString();
router.replace(`/analytics/me${qs ? `?${qs}` : ""}`);
}
}, [user, isLoading, router, searchParams]);

return (
<Suspense
fallback={
<div className="flex items-center justify-center min-h-[40vh]">
<Loader className="size-6 animate-spin text-muted-foreground" />
</div>
}
>
<AnalyticsGuard requires="overview">
<AnalyticsOverview />
</AnalyticsGuard>
</Suspense>
);
}
28 changes: 28 additions & 0 deletions app/[locale]/(sidebar)/analytics/staff/[employeeId]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Suspense } from "react";
import { Loader } from "lucide-react";
import { AnalyticsGuard, EmployeeDetail } from "@/src/features/analytics";

/**
* /analytics/staff/[employeeId] — drill-down по мастеру.
* Доступ как у /analytics/staff (Manager/Owner).
*/
export default async function EmployeeAnalyticsPage({
params,
}: {
params: Promise<{ employeeId: string }>;
}) {
const { employeeId } = await params;
return (
<Suspense
fallback={
<div className="flex items-center justify-center min-h-[40vh]">
<Loader className="size-6 animate-spin text-muted-foreground" />
</div>
}
>
<AnalyticsGuard requires="staff">
<EmployeeDetail employeeId={employeeId} />
</AnalyticsGuard>
</Suspense>
);
}
20 changes: 20 additions & 0 deletions app/[locale]/(sidebar)/analytics/staff/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Suspense } from "react";
import { Loader } from "lucide-react";
import { AnalyticsGuard, AnalyticsStaff } from "@/src/features/analytics";

/** /analytics/staff — список мастеров. Manager/Owner. */
export default function AnalyticsStaffPage() {
return (
<Suspense
fallback={
<div className="flex items-center justify-center min-h-[40vh]">
<Loader className="size-6 animate-spin text-muted-foreground" />
</div>
}
>
<AnalyticsGuard requires="staff">
<AnalyticsStaff />
</AnalyticsGuard>
</Suspense>
);
}
Loading