diff --git a/.gitignore b/.gitignore index a91efc3..d442d7e 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,9 @@ htmlcov/ .dmypy.json dmypy.json +# Test coverage reports +apps/web/coverage/ + # Node.js / npm / yarn / pnpm node_modules/ npm-debug.log* diff --git a/apps/web/__tests__/integration/auth-flow.test.tsx b/apps/web/__tests__/integration/auth-flow.test.tsx index 8e156c1..d234b3c 100644 --- a/apps/web/__tests__/integration/auth-flow.test.tsx +++ b/apps/web/__tests__/integration/auth-flow.test.tsx @@ -78,8 +78,8 @@ describe('Authentication Flow Integration', () => { // Fill out registration form await userEvent.type(screen.getByLabelText(/display name/i), 'New User'); await userEvent.type(screen.getByLabelText(/email/i), 'newuser@example.com'); - await userEvent.type(screen.getByLabelText(/^password$/i), 'SecurePass123'); - await userEvent.type(screen.getByLabelText(/confirm password/i), 'SecurePass123'); + await userEvent.type(screen.getByLabelText(/^password$/i), 'SecurePass123!'); + await userEvent.type(screen.getByLabelText(/confirm password/i), 'SecurePass123!'); // Submit form fireEvent.click(screen.getByRole('button', { name: /create account/i })); @@ -101,14 +101,14 @@ describe('Authentication Flow Integration', () => { 'credentials', expect.objectContaining({ email: 'newuser@example.com', - password: 'SecurePass123', + password: 'SecurePass123!', }) ); }); // Verify redirect await waitFor(() => { - expect(mockRouter.push).toHaveBeenCalledWith('/dashboard'); + expect(mockRouter.push).toHaveBeenCalledWith('/courses'); }); }); @@ -138,7 +138,7 @@ describe('Authentication Flow Integration', () => { // Verify redirect await waitFor(() => { - expect(mockRouter.push).toHaveBeenCalledWith('/dashboard'); + expect(mockRouter.push).toHaveBeenCalledWith('/courses'); }); }); }); @@ -147,7 +147,7 @@ describe('Authentication Flow Integration', () => { it('handles login failure gracefully', async () => { (signIn as jest.Mock).mockResolvedValue({ ok: false, - error: 'Invalid email or password', + error: 'CredentialsSignin', }); render(); @@ -177,8 +177,8 @@ describe('Authentication Flow Integration', () => { render(); await userEvent.type(screen.getByLabelText(/email/i), 'duplicate@example.com'); - await userEvent.type(screen.getByLabelText(/^password$/i), 'SecurePass123'); - await userEvent.type(screen.getByLabelText(/confirm password/i), 'SecurePass123'); + await userEvent.type(screen.getByLabelText(/^password$/i), 'SecurePass123!'); + await userEvent.type(screen.getByLabelText(/confirm password/i), 'SecurePass123!'); fireEvent.click(screen.getByRole('button', { name: /create account/i })); @@ -196,8 +196,8 @@ describe('Authentication Flow Integration', () => { render(); await userEvent.type(screen.getByLabelText(/email/i), 'test@example.com'); - await userEvent.type(screen.getByLabelText(/^password$/i), 'SecurePass123'); - await userEvent.type(screen.getByLabelText(/confirm password/i), 'SecurePass123'); + await userEvent.type(screen.getByLabelText(/^password$/i), 'SecurePass123!'); + await userEvent.type(screen.getByLabelText(/confirm password/i), 'SecurePass123!'); fireEvent.click(screen.getByRole('button', { name: /create account/i })); diff --git a/apps/web/__tests__/integration/study-flow.test.tsx b/apps/web/__tests__/integration/study-flow.test.tsx index 7c1ef0a..c2c8bb0 100644 --- a/apps/web/__tests__/integration/study-flow.test.tsx +++ b/apps/web/__tests__/integration/study-flow.test.tsx @@ -4,9 +4,18 @@ import userEvent from '@testing-library/user-event'; import { useSession } from 'next-auth/react'; import { useParams } from 'next/navigation'; -// scrollIntoView not implemented in jsdom +// scrollIntoView and matchMedia not implemented in jsdom beforeAll(() => { window.HTMLElement.prototype.scrollIntoView = jest.fn(); + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query: string) => ({ + matches: false, + media: query, + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + })), + }); }); // ── Module mocks ──────────────────────────────────────────────────────────── @@ -18,6 +27,7 @@ jest.mock('next-auth/react', () => ({ jest.mock('next/navigation', () => ({ useParams: jest.fn(), useRouter: jest.fn(() => ({ push: jest.fn() })), + useSearchParams: jest.fn(() => ({ get: jest.fn().mockReturnValue(null) })), })); jest.mock('@/lib/services/courses', () => ({ @@ -36,6 +46,7 @@ jest.mock('@/lib/services/documents', () => ({ jest.mock('@/lib/api/documents', () => ({ getDocumentPreviewView: jest.fn(), + getDocumentListRows: jest.fn(), })); jest.mock('@/lib/services/chat', () => ({ @@ -47,7 +58,7 @@ jest.mock('@/lib/services/chat', () => ({ import { getCourse, getCourseLessons } from '@/lib/services/courses'; import { getCourseProgress, markLessonComplete } from '@/lib/services/progress'; import { getDocuments } from '@/lib/services/documents'; -import { getDocumentPreviewView } from '@/lib/api/documents'; +import { getDocumentPreviewView, getDocumentListRows } from '@/lib/api/documents'; import { sendChatMessage } from '@/lib/services/chat'; // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -79,6 +90,7 @@ function setupMocks() { (getCourseLessons as jest.Mock).mockResolvedValue(LESSONS); (getCourseProgress as jest.Mock).mockResolvedValue(PROGRESS); (getDocuments as jest.Mock).mockResolvedValue([]); + (getDocumentListRows as jest.Mock).mockResolvedValue([]); (getDocumentPreviewView as jest.Mock).mockResolvedValue({ id: 'doc-1', filename: 'guide.pdf', @@ -191,7 +203,7 @@ describe('Study Flow Integration', () => { filename: 'bitcoin-guide.pdf', extractedTextPreview: null, pageCount: 5, - sections: [{ title: 'What is Bitcoin?' }], + sections: ['What is Bitcoin?'], sampleChunks: [ { text: 'Bitcoin is a decentralized digital currency.', section: 'What is Bitcoin?' }, { text: 'Transactions are verified by network nodes.', section: 'What is Bitcoin?' }, @@ -218,7 +230,7 @@ describe('Study Flow Integration', () => { filename: 'guide.pdf', extractedTextPreview: null, pageCount: 2, - sections: [{ title: 'Overview' }, { title: 'Key Concepts' }], + sections: ['Overview', 'Key Concepts'], sampleChunks: [{ text: 'Some chunk text.' }], }); @@ -313,7 +325,7 @@ describe('Study Flow Integration', () => { await waitFor(() => { expect(screen.getByText(/proof of work is the consensus mechanism/i)).toBeInTheDocument(); - expect(screen.getByText('Relevance: 88%')).toBeInTheDocument(); + expect(screen.getByText(/88%/)).toBeInTheDocument(); }); }); }); @@ -383,7 +395,7 @@ describe('Study Flow Integration', () => { fireEvent.click(screen.getByRole('button', { name: /mark as complete/i })); await waitFor(() => { - expect(screen.getByText(/new badge earned/i)).toBeInTheDocument(); + expect(screen.getByText(/badge earned/i)).toBeInTheDocument(); expect(screen.getByText('First Steps')).toBeInTheDocument(); }); }); diff --git a/apps/web/__tests__/unit/OutputPane.test.tsx b/apps/web/__tests__/unit/OutputPane.test.tsx index de1a91e..7457ce8 100644 --- a/apps/web/__tests__/unit/OutputPane.test.tsx +++ b/apps/web/__tests__/unit/OutputPane.test.tsx @@ -46,7 +46,7 @@ describe('OutputPane', () => { it('shows the empty-state prompt when no messages', () => { render(); - expect(screen.getByText(/ask me anything/i)).toBeInTheDocument(); + expect(screen.getByText(/type a topic/i)).toBeInTheDocument(); }); it('shows lesson-specific placeholder when a lesson is selected', () => { @@ -57,7 +57,7 @@ describe('OutputPane', () => { /> ); const textarea = screen.getByRole('textbox', { name: /message input/i }); - expect(textarea).toHaveAttribute('placeholder', 'Ask about "How Mining Works"…'); + expect(textarea).toHaveAttribute('placeholder', 'Ask about "How Mining Works" or pick an action above…'); }); }); @@ -178,7 +178,7 @@ describe('OutputPane', () => { fireEvent.click(screen.getByRole('button', { name: /send message/i })); await waitFor(() => { - expect(screen.getByText('Relevance: 92%')).toBeInTheDocument(); + expect(screen.getByText(/92%/)).toBeInTheDocument(); }); }); diff --git a/apps/web/__tests__/unit/login.test.tsx b/apps/web/__tests__/unit/login.test.tsx index 3749091..2331c4c 100644 --- a/apps/web/__tests__/unit/login.test.tsx +++ b/apps/web/__tests__/unit/login.test.tsx @@ -122,7 +122,7 @@ describe('LoginPage', () => { email: 'test@example.com', password: 'Password123', redirect: false, - callbackUrl: '/dashboard', + callbackUrl: '/courses', }); }); }); @@ -137,7 +137,7 @@ describe('LoginPage', () => { fireEvent.click(screen.getByRole('button', { name: /sign in/i })); await waitFor(() => { - expect(mockRouter.push).toHaveBeenCalledWith('/dashboard'); + expect(mockRouter.push).toHaveBeenCalledWith('/courses'); expect(mockRouter.refresh).toHaveBeenCalled(); }); }); @@ -167,7 +167,7 @@ describe('LoginPage', () => { }); it('displays error message on failed login', async () => { - (signIn as jest.Mock).mockResolvedValue({ ok: false, error: 'Invalid credentials' }); + (signIn as jest.Mock).mockResolvedValue({ ok: false, error: 'CredentialsSignin' }); render(); @@ -176,7 +176,7 @@ describe('LoginPage', () => { fireEvent.click(screen.getByRole('button', { name: /sign in/i })); await waitFor(() => { - expect(screen.getByText(/invalid credentials/i)).toBeInTheDocument(); + expect(screen.getByText(/invalid email or password/i)).toBeInTheDocument(); }); }); diff --git a/apps/web/__tests__/unit/signup.test.tsx b/apps/web/__tests__/unit/signup.test.tsx index 9d8fc2f..d626ed7 100644 --- a/apps/web/__tests__/unit/signup.test.tsx +++ b/apps/web/__tests__/unit/signup.test.tsx @@ -39,7 +39,7 @@ describe('SignupPage', () => { it('renders signup form with all elements', () => { render(); - expect(screen.getByRole('heading', { name: /create your account/i })).toBeInTheDocument(); + expect(screen.getByRole('heading', { name: /create account/i })).toBeInTheDocument(); expect(screen.getByLabelText(/display name/i)).toBeInTheDocument(); expect(screen.getByLabelText(/email/i)).toBeInTheDocument(); expect(screen.getByLabelText(/^password$/i)).toBeInTheDocument(); @@ -51,7 +51,7 @@ describe('SignupPage', () => { it('shows password requirements hint', () => { render(); - expect(screen.getByText(/min 8 characters/i)).toBeInTheDocument(); + expect(screen.getByText(/min 12/i)).toBeInTheDocument(); }); }); @@ -59,8 +59,8 @@ describe('SignupPage', () => { it('shows error when email is empty', async () => { render(); - await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123'); - await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123'); + await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123!'); + await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123!'); fireEvent.click(screen.getByRole('button', { name: /create account/i })); @@ -73,8 +73,8 @@ describe('SignupPage', () => { render(); await userEvent.type(screen.getByLabelText(/email/i), 'invalid-email'); - await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123'); - await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123'); + await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123!'); + await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123!'); fireEvent.click(screen.getByRole('button', { name: /create account/i })); @@ -93,7 +93,7 @@ describe('SignupPage', () => { fireEvent.click(screen.getByRole('button', { name: /create account/i })); await waitFor(() => { - expect(screen.getByText(/at least 8 characters/i)).toBeInTheDocument(); + expect(screen.getByText(/at least 12 characters/i)).toBeInTheDocument(); }); }); @@ -143,7 +143,7 @@ describe('SignupPage', () => { render(); await userEvent.type(screen.getByLabelText(/email/i), 'test@example.com'); - await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123'); + await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123!'); await userEvent.type(screen.getByLabelText(/confirm password/i), 'DifferentPass456'); fireEvent.click(screen.getByRole('button', { name: /create account/i })); @@ -157,7 +157,7 @@ describe('SignupPage', () => { render(); await userEvent.type(screen.getByLabelText(/email/i), 'test@example.com'); - await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123'); + await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123!'); fireEvent.click(screen.getByRole('button', { name: /create account/i })); @@ -179,8 +179,8 @@ describe('SignupPage', () => { render(); await userEvent.type(screen.getByLabelText(/email/i), 'test@example.com'); - await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123'); - await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123'); + await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123!'); + await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123!'); fireEvent.click(screen.getByRole('button', { name: /create account/i })); @@ -205,8 +205,8 @@ describe('SignupPage', () => { await userEvent.type(screen.getByLabelText(/display name/i), 'Test User'); await userEvent.type(screen.getByLabelText(/email/i), 'test@example.com'); - await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123'); - await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123'); + await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123!'); + await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123!'); fireEvent.click(screen.getByRole('button', { name: /create account/i })); @@ -218,7 +218,7 @@ describe('SignupPage', () => { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: 'test@example.com', - password: 'ValidPass123', + password: 'ValidPass123!', display_name: 'Test User', }), }) @@ -239,8 +239,8 @@ describe('SignupPage', () => { render(); await userEvent.type(screen.getByLabelText(/email/i), 'test@example.com'); - await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123'); - await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123'); + await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123!'); + await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123!'); fireEvent.click(screen.getByRole('button', { name: /create account/i })); @@ -249,7 +249,7 @@ describe('SignupPage', () => { 'credentials', expect.objectContaining({ email: 'test@example.com', - password: 'ValidPass123', + password: 'ValidPass123!', }) ); }); @@ -268,13 +268,13 @@ describe('SignupPage', () => { render(); await userEvent.type(screen.getByLabelText(/email/i), 'test@example.com'); - await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123'); - await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123'); + await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123!'); + await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123!'); fireEvent.click(screen.getByRole('button', { name: /create account/i })); await waitFor(() => { - expect(mockRouter.push).toHaveBeenCalledWith('/dashboard'); + expect(mockRouter.push).toHaveBeenCalledWith('/courses'); }); }); @@ -288,8 +288,8 @@ describe('SignupPage', () => { render(); await userEvent.type(screen.getByLabelText(/email/i), 'existing@example.com'); - await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123'); - await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123'); + await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123!'); + await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123!'); fireEvent.click(screen.getByRole('button', { name: /create account/i })); @@ -308,8 +308,8 @@ describe('SignupPage', () => { render(); await userEvent.type(screen.getByLabelText(/email/i), 'test@example.com'); - await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123'); - await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123'); + await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123!'); + await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123!'); fireEvent.click(screen.getByRole('button', { name: /create account/i })); @@ -326,8 +326,8 @@ describe('SignupPage', () => { render(); await userEvent.type(screen.getByLabelText(/email/i), 'test@example.com'); - await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123'); - await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123'); + await userEvent.type(screen.getByLabelText(/^password$/i), 'ValidPass123!'); + await userEvent.type(screen.getByLabelText(/confirm password/i), 'ValidPass123!'); fireEvent.click(screen.getByRole('button', { name: /create account/i })); diff --git a/apps/web/coverage/clover.xml b/apps/web/coverage/clover.xml deleted file mode 100644 index 6224420..0000000 --- a/apps/web/coverage/clover.xml +++ /dev/null @@ -1,760 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/web/coverage/coverage-final.json b/apps/web/coverage/coverage-final.json deleted file mode 100644 index 1bcce70..0000000 --- a/apps/web/coverage/coverage-final.json +++ /dev/null @@ -1,33 +0,0 @@ -{"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/middleware.ts": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/middleware.ts","statementMap":{"0":{"start":{"line":5,"column":36},"end":{"line":5,"column":50}},"1":{"start":{"line":5,"column":9},"end":{"line":5,"column":27}},"2":{"start":{"line":5,"column":50},"end":{"line":5,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":0,"1":0,"2":0},"f":{},"b":{}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/layout.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/layout.tsx","statementMap":{"0":{"start":{"line":11,"column":24},"end":{"line":11,"column":35}},"1":{"start":{"line":5,"column":13},"end":{"line":5,"column":21}},"2":{"start":{"line":2,"column":7},"end":{"line":2,"column":null}},"3":{"start":{"line":3,"column":29},"end":{"line":3,"column":null}},"4":{"start":{"line":5,"column":34},"end":{"line":9,"column":null}}},"fnMap":{"0":{"name":"RootLayout","decl":{"start":{"line":11,"column":24},"end":{"line":11,"column":35}},"loc":{"start":{"line":11,"column":78},"end":{"line":19,"column":1}}}},"branchMap":{},"s":{"0":0,"1":0,"2":0,"3":0,"4":0},"f":{"0":0},"b":{}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/page.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/page.tsx","statementMap":{"0":{"start":{"line":7,"column":24},"end":{"line":7,"column":null}},"1":{"start":{"line":3,"column":26},"end":{"line":3,"column":null}},"2":{"start":{"line":4,"column":26},"end":{"line":4,"column":null}},"3":{"start":{"line":5,"column":27},"end":{"line":5,"column":null}},"4":{"start":{"line":8,"column":17},"end":{"line":8,"column":null}},"5":{"start":{"line":9,"column":21},"end":{"line":9,"column":null}},"6":{"start":{"line":11,"column":2},"end":{"line":17,"column":null}},"7":{"start":{"line":12,"column":4},"end":{"line":16,"column":null}},"8":{"start":{"line":13,"column":6},"end":{"line":13,"column":null}},"9":{"start":{"line":14,"column":11},"end":{"line":16,"column":null}},"10":{"start":{"line":15,"column":6},"end":{"line":15,"column":null}},"11":{"start":{"line":19,"column":2},"end":{"line":27,"column":null}},"12":{"start":{"line":29,"column":2},"end":{"line":29,"column":null}}},"fnMap":{"0":{"name":"Home","decl":{"start":{"line":7,"column":24},"end":{"line":7,"column":null}},"loc":{"start":{"line":7,"column":24},"end":{"line":30,"column":null}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":11,"column":12},"end":{"line":11,"column":null}},"loc":{"start":{"line":11,"column":12},"end":{"line":17,"column":5}}}},"branchMap":{"0":{"loc":{"start":{"line":12,"column":4},"end":{"line":16,"column":null}},"type":"if","locations":[{"start":{"line":12,"column":4},"end":{"line":16,"column":null}},{"start":{"line":14,"column":11},"end":{"line":16,"column":null}}]},"1":{"loc":{"start":{"line":14,"column":11},"end":{"line":16,"column":null}},"type":"if","locations":[{"start":{"line":14,"column":11},"end":{"line":16,"column":null}}]},"2":{"loc":{"start":{"line":19,"column":2},"end":{"line":27,"column":null}},"type":"if","locations":[{"start":{"line":19,"column":2},"end":{"line":27,"column":null}}]},"3":{"loc":{"start":{"line":19,"column":6},"end":{"line":19,"column":60}},"type":"binary-expr","locations":[{"start":{"line":19,"column":6},"end":{"line":19,"column":30}},{"start":{"line":19,"column":30},"end":{"line":19,"column":60}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0},"f":{"0":0,"1":0},"b":{"0":[0,0],"1":[0],"2":[0],"3":[0,0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/(auth)/layout.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/(auth)/layout.tsx","statementMap":{"0":{"start":{"line":11,"column":24},"end":{"line":11,"column":35}}},"fnMap":{"0":{"name":"AuthLayout","decl":{"start":{"line":11,"column":24},"end":{"line":11,"column":35}},"loc":{"start":{"line":11,"column":64},"end":{"line":23,"column":null}}}},"branchMap":{},"s":{"0":0},"f":{"0":0},"b":{}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/(auth)/login/page.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/(auth)/login/page.tsx","statementMap":{"0":{"start":{"line":18,"column":24},"end":{"line":18,"column":null}},"1":{"start":{"line":7,"column":23},"end":{"line":7,"column":null}},"2":{"start":{"line":8,"column":17},"end":{"line":8,"column":null}},"3":{"start":{"line":9,"column":43},"end":{"line":9,"column":null}},"4":{"start":{"line":10,"column":36},"end":{"line":10,"column":null}},"5":{"start":{"line":19,"column":17},"end":{"line":19,"column":null}},"6":{"start":{"line":20,"column":23},"end":{"line":20,"column":null}},"7":{"start":{"line":21,"column":22},"end":{"line":21,"column":null}},"8":{"start":{"line":22,"column":21},"end":{"line":22,"column":null}},"9":{"start":{"line":24,"column":28},"end":{"line":24,"column":null}},"10":{"start":{"line":25,"column":34},"end":{"line":25,"column":null}},"11":{"start":{"line":26,"column":36},"end":{"line":26,"column":null}},"12":{"start":{"line":27,"column":30},"end":{"line":27,"column":null}},"13":{"start":{"line":31,"column":4},"end":{"line":31,"column":null}},"14":{"start":{"line":36,"column":23},"end":{"line":53,"column":null}},"15":{"start":{"line":37,"column":34},"end":{"line":37,"column":null}},"16":{"start":{"line":40,"column":4},"end":{"line":44,"column":null}},"17":{"start":{"line":41,"column":6},"end":{"line":41,"column":null}},"18":{"start":{"line":42,"column":11},"end":{"line":44,"column":null}},"19":{"start":{"line":43,"column":6},"end":{"line":43,"column":null}},"20":{"start":{"line":47,"column":4},"end":{"line":49,"column":null}},"21":{"start":{"line":48,"column":6},"end":{"line":48,"column":null}},"22":{"start":{"line":51,"column":4},"end":{"line":51,"column":null}},"23":{"start":{"line":52,"column":4},"end":{"line":52,"column":null}},"24":{"start":{"line":58,"column":23},"end":{"line":90,"column":null}},"25":{"start":{"line":59,"column":4},"end":{"line":59,"column":null}},"26":{"start":{"line":62,"column":4},"end":{"line":62,"column":null}},"27":{"start":{"line":65,"column":4},"end":{"line":67,"column":null}},"28":{"start":{"line":66,"column":6},"end":{"line":66,"column":null}},"29":{"start":{"line":69,"column":4},"end":{"line":69,"column":null}},"30":{"start":{"line":71,"column":4},"end":{"line":89,"column":null}},"31":{"start":{"line":72,"column":21},"end":{"line":77,"column":null}},"32":{"start":{"line":79,"column":6},"end":{"line":84,"column":null}},"33":{"start":{"line":80,"column":8},"end":{"line":80,"column":null}},"34":{"start":{"line":81,"column":13},"end":{"line":84,"column":null}},"35":{"start":{"line":82,"column":8},"end":{"line":82,"column":null}},"36":{"start":{"line":83,"column":8},"end":{"line":83,"column":null}},"37":{"start":{"line":86,"column":6},"end":{"line":86,"column":null}},"38":{"start":{"line":88,"column":6},"end":{"line":88,"column":null}},"39":{"start":{"line":124,"column":31},"end":{"line":124,"column":null}},"40":{"start":{"line":153,"column":31},"end":{"line":153,"column":null}}},"fnMap":{"0":{"name":"LoginPage","decl":{"start":{"line":18,"column":24},"end":{"line":18,"column":null}},"loc":{"start":{"line":18,"column":24},"end":{"line":229,"column":null}}},"1":{"name":"(anonymous_3)","decl":{"start":{"line":36,"column":23},"end":{"line":36,"column":null}},"loc":{"start":{"line":36,"column":23},"end":{"line":53,"column":null}}},"2":{"name":"(anonymous_4)","decl":{"start":{"line":58,"column":23},"end":{"line":58,"column":30}},"loc":{"start":{"line":58,"column":30},"end":{"line":90,"column":null}}},"3":{"name":"(anonymous_5)","decl":{"start":{"line":124,"column":24},"end":{"line":124,"column":25}},"loc":{"start":{"line":124,"column":31},"end":{"line":124,"column":null}}},"4":{"name":"(anonymous_6)","decl":{"start":{"line":153,"column":24},"end":{"line":153,"column":25}},"loc":{"start":{"line":153,"column":31},"end":{"line":153,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":21,"column":22},"end":{"line":21,"column":null}},"type":"binary-expr","locations":[{"start":{"line":21,"column":22},"end":{"line":21,"column":57}},{"start":{"line":21,"column":57},"end":{"line":21,"column":null}}]},"1":{"loc":{"start":{"line":31,"column":4},"end":{"line":31,"column":null}},"type":"cond-expr","locations":[{"start":{"line":31,"column":38},"end":{"line":31,"column":89}},{"start":{"line":31,"column":89},"end":{"line":31,"column":null}}]},"2":{"loc":{"start":{"line":40,"column":4},"end":{"line":44,"column":null}},"type":"if","locations":[{"start":{"line":40,"column":4},"end":{"line":44,"column":null}},{"start":{"line":42,"column":11},"end":{"line":44,"column":null}}]},"3":{"loc":{"start":{"line":42,"column":11},"end":{"line":44,"column":null}},"type":"if","locations":[{"start":{"line":42,"column":11},"end":{"line":44,"column":null}}]},"4":{"loc":{"start":{"line":47,"column":4},"end":{"line":49,"column":null}},"type":"if","locations":[{"start":{"line":47,"column":4},"end":{"line":49,"column":null}}]},"5":{"loc":{"start":{"line":65,"column":4},"end":{"line":67,"column":null}},"type":"if","locations":[{"start":{"line":65,"column":4},"end":{"line":67,"column":null}}]},"6":{"loc":{"start":{"line":79,"column":6},"end":{"line":84,"column":null}},"type":"if","locations":[{"start":{"line":79,"column":6},"end":{"line":84,"column":null}},{"start":{"line":81,"column":13},"end":{"line":84,"column":null}}]},"7":{"loc":{"start":{"line":81,"column":13},"end":{"line":84,"column":null}},"type":"if","locations":[{"start":{"line":81,"column":13},"end":{"line":84,"column":null}}]},"8":{"loc":{"start":{"line":97,"column":7},"end":{"line":97,"column":null}},"type":"binary-expr","locations":[{"start":{"line":97,"column":7},"end":{"line":97,"column":null}}]},"9":{"loc":{"start":{"line":104,"column":7},"end":{"line":104,"column":21}},"type":"binary-expr","locations":[{"start":{"line":104,"column":7},"end":{"line":104,"column":21}}]},"10":{"loc":{"start":{"line":126,"column":16},"end":{"line":126,"column":null}},"type":"cond-expr","locations":[{"start":{"line":126,"column":31},"end":{"line":126,"column":50}},{"start":{"line":126,"column":50},"end":{"line":126,"column":null}}]},"11":{"loc":{"start":{"line":129,"column":28},"end":{"line":129,"column":null}},"type":"cond-expr","locations":[{"start":{"line":129,"column":43},"end":{"line":129,"column":52}},{"start":{"line":129,"column":52},"end":{"line":129,"column":null}}]},"12":{"loc":{"start":{"line":130,"column":32},"end":{"line":130,"column":null}},"type":"cond-expr","locations":[{"start":{"line":130,"column":47},"end":{"line":130,"column":63}},{"start":{"line":130,"column":63},"end":{"line":130,"column":null}}]},"13":{"loc":{"start":{"line":133,"column":11},"end":{"line":133,"column":23}},"type":"binary-expr","locations":[{"start":{"line":133,"column":11},"end":{"line":133,"column":23}}]},"14":{"loc":{"start":{"line":155,"column":16},"end":{"line":155,"column":null}},"type":"cond-expr","locations":[{"start":{"line":155,"column":34},"end":{"line":155,"column":53}},{"start":{"line":155,"column":53},"end":{"line":155,"column":null}}]},"15":{"loc":{"start":{"line":158,"column":28},"end":{"line":158,"column":null}},"type":"cond-expr","locations":[{"start":{"line":158,"column":46},"end":{"line":158,"column":55}},{"start":{"line":158,"column":55},"end":{"line":158,"column":null}}]},"16":{"loc":{"start":{"line":159,"column":32},"end":{"line":159,"column":null}},"type":"cond-expr","locations":[{"start":{"line":159,"column":50},"end":{"line":159,"column":69}},{"start":{"line":159,"column":69},"end":{"line":159,"column":null}}]},"17":{"loc":{"start":{"line":162,"column":11},"end":{"line":162,"column":26}},"type":"binary-expr","locations":[{"start":{"line":162,"column":11},"end":{"line":162,"column":26}}]},"18":{"loc":{"start":{"line":176,"column":13},"end":{"line":201,"column":null}},"type":"cond-expr","locations":[{"start":{"line":177,"column":14},"end":{"line":201,"column":null}},{"start":{"line":201,"column":14},"end":{"line":201,"column":null}}]}},"s":{"0":2,"1":2,"2":2,"3":2,"4":2,"5":327,"6":327,"7":327,"8":327,"9":327,"10":325,"11":325,"12":325,"13":325,"14":325,"15":15,"16":15,"17":3,"18":12,"19":2,"20":15,"21":6,"22":15,"23":15,"24":325,"25":15,"26":15,"27":15,"28":6,"29":9,"30":9,"31":9,"32":8,"33":2,"34":6,"35":6,"36":6,"37":0,"38":8,"39":179,"40":106},"f":{"0":327,"1":15,"2":15,"3":179,"4":106},"b":{"0":[327,262],"1":[36,289],"2":[3,12],"3":[2],"4":[6],"5":[6],"6":[2,6],"7":[6],"8":[325],"9":[325],"10":[6,319],"11":[6,319],"12":[6,319],"13":[325],"14":[7,318],"15":[7,318],"16":[7,318],"17":[325],"18":[9,316]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/(auth)/signup/page.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/(auth)/signup/page.tsx","statementMap":{"0":{"start":{"line":23,"column":24},"end":{"line":23,"column":null}},"1":{"start":{"line":7,"column":17},"end":{"line":7,"column":null}},"2":{"start":{"line":8,"column":26},"end":{"line":8,"column":null}},"3":{"start":{"line":9,"column":23},"end":{"line":9,"column":null}},"4":{"start":{"line":10,"column":36},"end":{"line":10,"column":null}},"5":{"start":{"line":13,"column":16},"end":{"line":13,"column":null}},"6":{"start":{"line":24,"column":17},"end":{"line":24,"column":null}},"7":{"start":{"line":26,"column":28},"end":{"line":26,"column":null}},"8":{"start":{"line":27,"column":34},"end":{"line":27,"column":null}},"9":{"start":{"line":28,"column":48},"end":{"line":28,"column":null}},"10":{"start":{"line":29,"column":40},"end":{"line":29,"column":null}},"11":{"start":{"line":30,"column":36},"end":{"line":30,"column":null}},"12":{"start":{"line":31,"column":30},"end":{"line":31,"column":null}},"13":{"start":{"line":36,"column":23},"end":{"line":73,"column":null}},"14":{"start":{"line":37,"column":34},"end":{"line":37,"column":null}},"15":{"start":{"line":40,"column":4},"end":{"line":44,"column":null}},"16":{"start":{"line":41,"column":6},"end":{"line":41,"column":null}},"17":{"start":{"line":42,"column":11},"end":{"line":44,"column":null}},"18":{"start":{"line":43,"column":6},"end":{"line":43,"column":null}},"19":{"start":{"line":47,"column":4},"end":{"line":57,"column":null}},"20":{"start":{"line":48,"column":6},"end":{"line":48,"column":null}},"21":{"start":{"line":49,"column":11},"end":{"line":57,"column":null}},"22":{"start":{"line":50,"column":6},"end":{"line":50,"column":null}},"23":{"start":{"line":51,"column":11},"end":{"line":57,"column":null}},"24":{"start":{"line":52,"column":6},"end":{"line":52,"column":null}},"25":{"start":{"line":53,"column":11},"end":{"line":57,"column":null}},"26":{"start":{"line":54,"column":6},"end":{"line":54,"column":null}},"27":{"start":{"line":55,"column":11},"end":{"line":57,"column":null}},"28":{"start":{"line":56,"column":6},"end":{"line":56,"column":null}},"29":{"start":{"line":60,"column":4},"end":{"line":64,"column":null}},"30":{"start":{"line":61,"column":6},"end":{"line":61,"column":null}},"31":{"start":{"line":62,"column":11},"end":{"line":64,"column":null}},"32":{"start":{"line":63,"column":6},"end":{"line":63,"column":null}},"33":{"start":{"line":67,"column":4},"end":{"line":69,"column":null}},"34":{"start":{"line":68,"column":6},"end":{"line":68,"column":null}},"35":{"start":{"line":71,"column":4},"end":{"line":71,"column":null}},"36":{"start":{"line":72,"column":4},"end":{"line":72,"column":null}},"37":{"start":{"line":78,"column":23},"end":{"line":138,"column":null}},"38":{"start":{"line":79,"column":4},"end":{"line":79,"column":null}},"39":{"start":{"line":82,"column":4},"end":{"line":82,"column":null}},"40":{"start":{"line":85,"column":4},"end":{"line":87,"column":null}},"41":{"start":{"line":86,"column":6},"end":{"line":86,"column":null}},"42":{"start":{"line":89,"column":4},"end":{"line":89,"column":null}},"43":{"start":{"line":91,"column":4},"end":{"line":137,"column":null}},"44":{"start":{"line":93,"column":31},"end":{"line":103,"column":null}},"45":{"start":{"line":105,"column":6},"end":{"line":116,"column":null}},"46":{"start":{"line":106,"column":22},"end":{"line":106,"column":null}},"47":{"start":{"line":108,"column":8},"end":{"line":114,"column":null}},"48":{"start":{"line":109,"column":10},"end":{"line":109,"column":null}},"49":{"start":{"line":110,"column":15},"end":{"line":114,"column":null}},"50":{"start":{"line":111,"column":10},"end":{"line":111,"column":null}},"51":{"start":{"line":113,"column":10},"end":{"line":113,"column":null}},"52":{"start":{"line":115,"column":8},"end":{"line":115,"column":null}},"53":{"start":{"line":119,"column":21},"end":{"line":124,"column":null}},"54":{"start":{"line":126,"column":6},"end":{"line":132,"column":null}},"55":{"start":{"line":128,"column":8},"end":{"line":128,"column":null}},"56":{"start":{"line":129,"column":13},"end":{"line":132,"column":null}},"57":{"start":{"line":130,"column":8},"end":{"line":130,"column":null}},"58":{"start":{"line":131,"column":8},"end":{"line":131,"column":null}},"59":{"start":{"line":134,"column":6},"end":{"line":134,"column":null}},"60":{"start":{"line":136,"column":6},"end":{"line":136,"column":null}},"61":{"start":{"line":164,"column":31},"end":{"line":164,"column":null}},"62":{"start":{"line":193,"column":31},"end":{"line":193,"column":null}},"63":{"start":{"line":222,"column":31},"end":{"line":222,"column":null}},"64":{"start":{"line":255,"column":31},"end":{"line":255,"column":null}}},"fnMap":{"0":{"name":"SignupPage","decl":{"start":{"line":23,"column":24},"end":{"line":23,"column":null}},"loc":{"start":{"line":23,"column":24},"end":{"line":331,"column":null}}},"1":{"name":"(anonymous_3)","decl":{"start":{"line":36,"column":23},"end":{"line":36,"column":null}},"loc":{"start":{"line":36,"column":23},"end":{"line":73,"column":null}}},"2":{"name":"(anonymous_4)","decl":{"start":{"line":78,"column":23},"end":{"line":78,"column":30}},"loc":{"start":{"line":78,"column":30},"end":{"line":138,"column":null}}},"3":{"name":"(anonymous_5)","decl":{"start":{"line":164,"column":24},"end":{"line":164,"column":25}},"loc":{"start":{"line":164,"column":31},"end":{"line":164,"column":null}}},"4":{"name":"(anonymous_6)","decl":{"start":{"line":193,"column":24},"end":{"line":193,"column":25}},"loc":{"start":{"line":193,"column":31},"end":{"line":193,"column":null}}},"5":{"name":"(anonymous_7)","decl":{"start":{"line":222,"column":24},"end":{"line":222,"column":25}},"loc":{"start":{"line":222,"column":31},"end":{"line":222,"column":null}}},"6":{"name":"(anonymous_8)","decl":{"start":{"line":255,"column":24},"end":{"line":255,"column":25}},"loc":{"start":{"line":255,"column":31},"end":{"line":255,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":13,"column":16},"end":{"line":13,"column":null}},"type":"binary-expr","locations":[{"start":{"line":13,"column":16},"end":{"line":13,"column":47}},{"start":{"line":13,"column":51},"end":{"line":13,"column":null}}]},"1":{"loc":{"start":{"line":40,"column":4},"end":{"line":44,"column":null}},"type":"if","locations":[{"start":{"line":40,"column":4},"end":{"line":44,"column":null}},{"start":{"line":42,"column":11},"end":{"line":44,"column":null}}]},"2":{"loc":{"start":{"line":42,"column":11},"end":{"line":44,"column":null}},"type":"if","locations":[{"start":{"line":42,"column":11},"end":{"line":44,"column":null}}]},"3":{"loc":{"start":{"line":47,"column":4},"end":{"line":57,"column":null}},"type":"if","locations":[{"start":{"line":47,"column":4},"end":{"line":57,"column":null}},{"start":{"line":49,"column":11},"end":{"line":57,"column":null}}]},"4":{"loc":{"start":{"line":49,"column":11},"end":{"line":57,"column":null}},"type":"if","locations":[{"start":{"line":49,"column":11},"end":{"line":57,"column":null}},{"start":{"line":51,"column":11},"end":{"line":57,"column":null}}]},"5":{"loc":{"start":{"line":51,"column":11},"end":{"line":57,"column":null}},"type":"if","locations":[{"start":{"line":51,"column":11},"end":{"line":57,"column":null}},{"start":{"line":53,"column":11},"end":{"line":57,"column":null}}]},"6":{"loc":{"start":{"line":53,"column":11},"end":{"line":57,"column":null}},"type":"if","locations":[{"start":{"line":53,"column":11},"end":{"line":57,"column":null}},{"start":{"line":55,"column":11},"end":{"line":57,"column":null}}]},"7":{"loc":{"start":{"line":55,"column":11},"end":{"line":57,"column":null}},"type":"if","locations":[{"start":{"line":55,"column":11},"end":{"line":57,"column":null}}]},"8":{"loc":{"start":{"line":60,"column":4},"end":{"line":64,"column":null}},"type":"if","locations":[{"start":{"line":60,"column":4},"end":{"line":64,"column":null}},{"start":{"line":62,"column":11},"end":{"line":64,"column":null}}]},"9":{"loc":{"start":{"line":62,"column":11},"end":{"line":64,"column":null}},"type":"if","locations":[{"start":{"line":62,"column":11},"end":{"line":64,"column":null}}]},"10":{"loc":{"start":{"line":67,"column":4},"end":{"line":69,"column":null}},"type":"if","locations":[{"start":{"line":67,"column":4},"end":{"line":69,"column":null}}]},"11":{"loc":{"start":{"line":67,"column":8},"end":{"line":67,"column":47}},"type":"binary-expr","locations":[{"start":{"line":67,"column":8},"end":{"line":67,"column":23}},{"start":{"line":67,"column":23},"end":{"line":67,"column":47}}]},"12":{"loc":{"start":{"line":85,"column":4},"end":{"line":87,"column":null}},"type":"if","locations":[{"start":{"line":85,"column":4},"end":{"line":87,"column":null}}]},"13":{"loc":{"start":{"line":101,"column":24},"end":{"line":101,"column":null}},"type":"binary-expr","locations":[{"start":{"line":101,"column":24},"end":{"line":101,"column":39}},{"start":{"line":101,"column":39},"end":{"line":101,"column":null}}]},"14":{"loc":{"start":{"line":105,"column":6},"end":{"line":116,"column":null}},"type":"if","locations":[{"start":{"line":105,"column":6},"end":{"line":116,"column":null}}]},"15":{"loc":{"start":{"line":108,"column":8},"end":{"line":114,"column":null}},"type":"if","locations":[{"start":{"line":108,"column":8},"end":{"line":114,"column":null}},{"start":{"line":110,"column":15},"end":{"line":114,"column":null}}]},"16":{"loc":{"start":{"line":110,"column":15},"end":{"line":114,"column":null}},"type":"if","locations":[{"start":{"line":110,"column":15},"end":{"line":114,"column":null}},{"start":{"line":112,"column":15},"end":{"line":114,"column":null}}]},"17":{"loc":{"start":{"line":111,"column":31},"end":{"line":111,"column":68}},"type":"binary-expr","locations":[{"start":{"line":111,"column":31},"end":{"line":111,"column":43}},{"start":{"line":111,"column":47},"end":{"line":111,"column":68}}]},"18":{"loc":{"start":{"line":113,"column":31},"end":{"line":113,"column":69}},"type":"binary-expr","locations":[{"start":{"line":113,"column":31},"end":{"line":113,"column":43}},{"start":{"line":113,"column":47},"end":{"line":113,"column":69}}]},"19":{"loc":{"start":{"line":126,"column":6},"end":{"line":132,"column":null}},"type":"if","locations":[{"start":{"line":126,"column":6},"end":{"line":132,"column":null}},{"start":{"line":129,"column":13},"end":{"line":132,"column":null}}]},"20":{"loc":{"start":{"line":129,"column":13},"end":{"line":132,"column":null}},"type":"if","locations":[{"start":{"line":129,"column":13},"end":{"line":132,"column":null}}]},"21":{"loc":{"start":{"line":145,"column":7},"end":{"line":145,"column":21}},"type":"binary-expr","locations":[{"start":{"line":145,"column":7},"end":{"line":145,"column":21}}]},"22":{"loc":{"start":{"line":166,"column":16},"end":{"line":166,"column":null}},"type":"cond-expr","locations":[{"start":{"line":166,"column":37},"end":{"line":166,"column":56}},{"start":{"line":166,"column":56},"end":{"line":166,"column":null}}]},"23":{"loc":{"start":{"line":169,"column":28},"end":{"line":169,"column":null}},"type":"cond-expr","locations":[{"start":{"line":169,"column":49},"end":{"line":169,"column":58}},{"start":{"line":169,"column":58},"end":{"line":169,"column":null}}]},"24":{"loc":{"start":{"line":170,"column":32},"end":{"line":170,"column":null}},"type":"cond-expr","locations":[{"start":{"line":170,"column":53},"end":{"line":170,"column":75}},{"start":{"line":170,"column":75},"end":{"line":170,"column":null}}]},"25":{"loc":{"start":{"line":173,"column":11},"end":{"line":173,"column":29}},"type":"binary-expr","locations":[{"start":{"line":173,"column":11},"end":{"line":173,"column":29}}]},"26":{"loc":{"start":{"line":195,"column":16},"end":{"line":195,"column":null}},"type":"cond-expr","locations":[{"start":{"line":195,"column":31},"end":{"line":195,"column":50}},{"start":{"line":195,"column":50},"end":{"line":195,"column":null}}]},"27":{"loc":{"start":{"line":198,"column":28},"end":{"line":198,"column":null}},"type":"cond-expr","locations":[{"start":{"line":198,"column":43},"end":{"line":198,"column":52}},{"start":{"line":198,"column":52},"end":{"line":198,"column":null}}]},"28":{"loc":{"start":{"line":199,"column":32},"end":{"line":199,"column":null}},"type":"cond-expr","locations":[{"start":{"line":199,"column":47},"end":{"line":199,"column":63}},{"start":{"line":199,"column":63},"end":{"line":199,"column":null}}]},"29":{"loc":{"start":{"line":202,"column":11},"end":{"line":202,"column":23}},"type":"binary-expr","locations":[{"start":{"line":202,"column":11},"end":{"line":202,"column":23}}]},"30":{"loc":{"start":{"line":224,"column":16},"end":{"line":224,"column":null}},"type":"cond-expr","locations":[{"start":{"line":224,"column":34},"end":{"line":224,"column":53}},{"start":{"line":224,"column":53},"end":{"line":224,"column":null}}]},"31":{"loc":{"start":{"line":227,"column":28},"end":{"line":227,"column":null}},"type":"cond-expr","locations":[{"start":{"line":227,"column":46},"end":{"line":227,"column":55}},{"start":{"line":227,"column":55},"end":{"line":227,"column":null}}]},"32":{"loc":{"start":{"line":228,"column":32},"end":{"line":228,"column":null}},"type":"cond-expr","locations":[{"start":{"line":228,"column":50},"end":{"line":228,"column":69}},{"start":{"line":228,"column":69},"end":{"line":228,"column":null}}]},"33":{"loc":{"start":{"line":232,"column":12},"end":{"line":236,"column":13}},"type":"cond-expr","locations":[{"start":{"line":232,"column":12},"end":{"line":236,"column":13}}]},"34":{"loc":{"start":{"line":257,"column":16},"end":{"line":257,"column":null}},"type":"cond-expr","locations":[{"start":{"line":257,"column":41},"end":{"line":257,"column":60}},{"start":{"line":257,"column":60},"end":{"line":257,"column":null}}]},"35":{"loc":{"start":{"line":260,"column":28},"end":{"line":260,"column":null}},"type":"cond-expr","locations":[{"start":{"line":260,"column":53},"end":{"line":260,"column":62}},{"start":{"line":260,"column":62},"end":{"line":260,"column":null}}]},"36":{"loc":{"start":{"line":261,"column":32},"end":{"line":261,"column":null}},"type":"cond-expr","locations":[{"start":{"line":261,"column":57},"end":{"line":261,"column":83}},{"start":{"line":261,"column":83},"end":{"line":261,"column":null}}]},"37":{"loc":{"start":{"line":264,"column":11},"end":{"line":264,"column":33}},"type":"binary-expr","locations":[{"start":{"line":264,"column":11},"end":{"line":264,"column":33}}]},"38":{"loc":{"start":{"line":278,"column":13},"end":{"line":303,"column":null}},"type":"cond-expr","locations":[{"start":{"line":279,"column":14},"end":{"line":303,"column":null}},{"start":{"line":303,"column":14},"end":{"line":303,"column":null}}]}},"s":{"0":2,"1":2,"2":2,"3":2,"4":2,"5":2,"6":774,"7":774,"8":772,"9":772,"10":772,"11":772,"12":772,"13":772,"14":18,"15":18,"16":1,"17":17,"18":1,"19":18,"20":0,"21":18,"22":1,"23":17,"24":1,"25":16,"26":1,"27":15,"28":1,"29":18,"30":1,"31":17,"32":1,"33":18,"34":0,"35":18,"36":18,"37":772,"38":18,"39":18,"40":18,"41":8,"42":10,"43":10,"44":10,"45":8,"46":3,"47":3,"48":2,"49":1,"50":0,"51":1,"52":3,"53":5,"54":5,"55":0,"56":5,"57":5,"58":5,"59":1,"60":9,"61":17,"62":281,"63":217,"64":209},"f":{"0":774,"1":18,"2":18,"3":17,"4":281,"5":217,"6":209},"b":{"0":[2,2],"1":[1,17],"2":[1],"3":[0,18],"4":[1,17],"5":[1,16],"6":[1,15],"7":[1],"8":[1,17],"9":[1],"10":[0],"11":[18,2],"12":[8],"13":[10,8],"14":[3],"15":[2,1],"16":[0,1],"17":[0,0],"18":[1,0],"19":[0,5],"20":[5],"21":[772],"22":[0,772],"23":[0,772],"24":[0,772],"25":[772],"26":[4,768],"27":[4,768],"28":[4,768],"29":[772],"30":[4,768],"31":[4,768],"32":[4,768],"33":[4],"34":[2,770],"35":[2,770],"36":[2,770],"37":[772],"38":[10,762]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/api/auth/[...nextauth]/route.ts": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/api/auth/[...nextauth]/route.ts","statementMap":{"0":{"start":{"line":9,"column":9},"end":{"line":9,"column":20}},"1":{"start":{"line":9,"column":25},"end":{"line":9,"column":36}},"2":{"start":{"line":4,"column":21},"end":{"line":4,"column":null}},"3":{"start":{"line":5,"column":28},"end":{"line":5,"column":null}},"4":{"start":{"line":7,"column":16},"end":{"line":7,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":0,"1":0,"2":0,"3":0,"4":0},"f":{},"b":{}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/courses/page.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/courses/page.tsx","statementMap":{"0":{"start":{"line":10,"column":24},"end":{"line":10,"column":null}},"1":{"start":{"line":3,"column":36},"end":{"line":3,"column":null}},"2":{"start":{"line":4,"column":27},"end":{"line":4,"column":null}},"3":{"start":{"line":5,"column":26},"end":{"line":5,"column":null}},"4":{"start":{"line":6,"column":17},"end":{"line":6,"column":null}},"5":{"start":{"line":7,"column":40},"end":{"line":7,"column":null}},"6":{"start":{"line":8,"column":27},"end":{"line":8,"column":null}},"7":{"start":{"line":11,"column":36},"end":{"line":11,"column":null}},"8":{"start":{"line":12,"column":17},"end":{"line":12,"column":null}},"9":{"start":{"line":13,"column":32},"end":{"line":13,"column":null}},"10":{"start":{"line":14,"column":32},"end":{"line":14,"column":null}},"11":{"start":{"line":15,"column":28},"end":{"line":15,"column":null}},"12":{"start":{"line":17,"column":2},"end":{"line":36,"column":null}},"13":{"start":{"line":18,"column":4},"end":{"line":21,"column":null}},"14":{"start":{"line":19,"column":6},"end":{"line":19,"column":null}},"15":{"start":{"line":20,"column":6},"end":{"line":20,"column":null}},"16":{"start":{"line":22,"column":4},"end":{"line":22,"column":null}},"17":{"start":{"line":22,"column":36},"end":{"line":22,"column":null}},"18":{"start":{"line":25,"column":6},"end":{"line":32,"column":null}},"19":{"start":{"line":26,"column":21},"end":{"line":26,"column":null}},"20":{"start":{"line":27,"column":8},"end":{"line":27,"column":null}},"21":{"start":{"line":29,"column":8},"end":{"line":29,"column":null}},"22":{"start":{"line":31,"column":8},"end":{"line":31,"column":null}},"23":{"start":{"line":35,"column":4},"end":{"line":35,"column":null}},"24":{"start":{"line":38,"column":2},"end":{"line":60,"column":null}},"25":{"start":{"line":49,"column":14},"end":{"line":49,"column":27}},"26":{"start":{"line":80,"column":29},"end":{"line":80,"column":null}},"27":{"start":{"line":97,"column":14},"end":{"line":97,"column":42}}},"fnMap":{"0":{"name":"CoursesPage","decl":{"start":{"line":10,"column":24},"end":{"line":10,"column":null}},"loc":{"start":{"line":10,"column":24},"end":{"line":104,"column":null}}},"1":{"name":"(anonymous_3)","decl":{"start":{"line":17,"column":12},"end":{"line":17,"column":null}},"loc":{"start":{"line":17,"column":12},"end":{"line":36,"column":5}}},"2":{"name":"fetchCourses","decl":{"start":{"line":24,"column":19},"end":{"line":24,"column":null}},"loc":{"start":{"line":24,"column":19},"end":{"line":33,"column":null}}},"3":{"name":"(anonymous_5)","decl":{"start":{"line":48,"column":27},"end":{"line":48,"column":28}},"loc":{"start":{"line":49,"column":14},"end":{"line":49,"column":27}}},"4":{"name":"(anonymous_6)","decl":{"start":{"line":80,"column":23},"end":{"line":80,"column":29}},"loc":{"start":{"line":80,"column":29},"end":{"line":80,"column":null}}},"5":{"name":"(anonymous_7)","decl":{"start":{"line":96,"column":25},"end":{"line":96,"column":26}},"loc":{"start":{"line":97,"column":14},"end":{"line":97,"column":42}}}},"branchMap":{"0":{"loc":{"start":{"line":18,"column":4},"end":{"line":21,"column":null}},"type":"if","locations":[{"start":{"line":18,"column":4},"end":{"line":21,"column":null}}]},"1":{"loc":{"start":{"line":22,"column":4},"end":{"line":22,"column":null}},"type":"if","locations":[{"start":{"line":22,"column":4},"end":{"line":22,"column":null}}]},"2":{"loc":{"start":{"line":29,"column":17},"end":{"line":29,"column":null}},"type":"cond-expr","locations":[{"start":{"line":29,"column":40},"end":{"line":29,"column":51}},{"start":{"line":29,"column":54},"end":{"line":29,"column":null}}]},"3":{"loc":{"start":{"line":38,"column":2},"end":{"line":60,"column":null}},"type":"if","locations":[{"start":{"line":38,"column":2},"end":{"line":60,"column":null}}]},"4":{"loc":{"start":{"line":38,"column":6},"end":{"line":38,"column":71}},"type":"binary-expr","locations":[{"start":{"line":38,"column":6},"end":{"line":38,"column":31}},{"start":{"line":38,"column":31},"end":{"line":38,"column":61}},{"start":{"line":38,"column":61},"end":{"line":38,"column":71}}]},"5":{"loc":{"start":{"line":77,"column":10},"end":{"line":86,"column":20}},"type":"cond-expr","locations":[{"start":{"line":77,"column":10},"end":{"line":86,"column":20}}]},"6":{"loc":{"start":{"line":87,"column":10},"end":{"line":95,"column":11}},"type":"cond-expr","locations":[{"start":{"line":87,"column":10},"end":{"line":95,"column":11}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0},"b":{"0":[0],"1":[0],"2":[0,0],"3":[0],"4":[0,0,0],"5":[0],"6":[0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/courses/[courseId]/layout.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/courses/[courseId]/layout.tsx","statementMap":{"0":{"start":{"line":11,"column":24},"end":{"line":11,"column":37}},"1":{"start":{"line":3,"column":17},"end":{"line":3,"column":null}},"2":{"start":{"line":4,"column":39},"end":{"line":4,"column":null}},"3":{"start":{"line":12,"column":17},"end":{"line":12,"column":null}},"4":{"start":{"line":13,"column":19},"end":{"line":13,"column":null}},"5":{"start":{"line":14,"column":19},"end":{"line":14,"column":34}},"6":{"start":{"line":16,"column":19},"end":{"line":19,"column":null}},"7":{"start":{"line":22,"column":4},"end":{"line":22,"column":null}},"8":{"start":{"line":44,"column":14},"end":{"line":45,"column":null}}},"fnMap":{"0":{"name":"CourseLayout","decl":{"start":{"line":11,"column":24},"end":{"line":11,"column":37}},"loc":{"start":{"line":11,"column":68},"end":{"line":62,"column":null}}},"1":{"name":"isActive","decl":{"start":{"line":21,"column":11},"end":{"line":21,"column":20}},"loc":{"start":{"line":21,"column":49},"end":{"line":23,"column":null}}},"2":{"name":"(anonymous_4)","decl":{"start":{"line":43,"column":26},"end":{"line":43,"column":27}},"loc":{"start":{"line":44,"column":14},"end":{"line":45,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":22,"column":11},"end":{"line":22,"column":null}},"type":"cond-expr","locations":[{"start":{"line":22,"column":19},"end":{"line":22,"column":39}},{"start":{"line":22,"column":39},"end":{"line":22,"column":null}}]},"1":{"loc":{"start":{"line":48,"column":18},"end":{"line":50,"column":null}},"type":"cond-expr","locations":[{"start":{"line":49,"column":22},"end":{"line":49,"column":null}},{"start":{"line":50,"column":22},"end":{"line":50,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0},"f":{"0":0,"1":0,"2":0},"b":{"0":[0,0],"1":[0,0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/courses/[courseId]/page.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/courses/[courseId]/page.tsx","statementMap":{"0":{"start":{"line":10,"column":24},"end":{"line":10,"column":null}},"1":{"start":{"line":3,"column":49},"end":{"line":3,"column":null}},"2":{"start":{"line":4,"column":37},"end":{"line":4,"column":null}},"3":{"start":{"line":5,"column":27},"end":{"line":5,"column":null}},"4":{"start":{"line":6,"column":70},"end":{"line":6,"column":null}},"5":{"start":{"line":7,"column":29},"end":{"line":7,"column":null}},"6":{"start":{"line":8,"column":31},"end":{"line":8,"column":null}},"7":{"start":{"line":11,"column":17},"end":{"line":11,"column":null}},"8":{"start":{"line":12,"column":17},"end":{"line":12,"column":null}},"9":{"start":{"line":13,"column":19},"end":{"line":13,"column":34}},"10":{"start":{"line":14,"column":28},"end":{"line":14,"column":null}},"11":{"start":{"line":15,"column":23},"end":{"line":15,"column":null}},"12":{"start":{"line":17,"column":30},"end":{"line":17,"column":null}},"13":{"start":{"line":18,"column":32},"end":{"line":18,"column":null}},"14":{"start":{"line":19,"column":32},"end":{"line":19,"column":null}},"15":{"start":{"line":20,"column":28},"end":{"line":20,"column":null}},"16":{"start":{"line":21,"column":44},"end":{"line":21,"column":null}},"17":{"start":{"line":23,"column":27},"end":{"line":25,"column":null}},"18":{"start":{"line":24,"column":4},"end":{"line":24,"column":null}},"19":{"start":{"line":24,"column":28},"end":{"line":24,"column":null}},"20":{"start":{"line":28,"column":4},"end":{"line":28,"column":null}},"21":{"start":{"line":31,"column":2},"end":{"line":48,"column":null}},"22":{"start":{"line":33,"column":6},"end":{"line":44,"column":null}},"23":{"start":{"line":34,"column":42},"end":{"line":37,"column":null}},"24":{"start":{"line":38,"column":8},"end":{"line":38,"column":null}},"25":{"start":{"line":39,"column":8},"end":{"line":39,"column":null}},"26":{"start":{"line":41,"column":8},"end":{"line":41,"column":null}},"27":{"start":{"line":43,"column":8},"end":{"line":43,"column":null}},"28":{"start":{"line":47,"column":4},"end":{"line":47,"column":null}},"29":{"start":{"line":47,"column":18},"end":{"line":47,"column":null}},"30":{"start":{"line":50,"column":2},"end":{"line":71,"column":null}},"31":{"start":{"line":60,"column":16},"end":{"line":60,"column":29}},"32":{"start":{"line":73,"column":2},"end":{"line":87,"column":null}},"33":{"start":{"line":79,"column":27},"end":{"line":79,"column":null}},"34":{"start":{"line":116,"column":20},"end":{"line":116,"column":40}}},"fnMap":{"0":{"name":"CourseWorkspacePage","decl":{"start":{"line":10,"column":24},"end":{"line":10,"column":null}},"loc":{"start":{"line":10,"column":24},"end":{"line":157,"column":null}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":23,"column":39},"end":{"line":23,"column":null}},"loc":{"start":{"line":23,"column":39},"end":{"line":25,"column":5}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":24,"column":21},"end":{"line":24,"column":22}},"loc":{"start":{"line":24,"column":28},"end":{"line":24,"column":null}}},"3":{"name":"handleViewPreview","decl":{"start":{"line":27,"column":11},"end":{"line":27,"column":29}},"loc":{"start":{"line":27,"column":47},"end":{"line":29,"column":null}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":31,"column":12},"end":{"line":31,"column":null}},"loc":{"start":{"line":31,"column":12},"end":{"line":48,"column":5}}},"5":{"name":"load","decl":{"start":{"line":32,"column":19},"end":{"line":32,"column":null}},"loc":{"start":{"line":32,"column":19},"end":{"line":45,"column":null}}},"6":{"name":"(anonymous_7)","decl":{"start":{"line":59,"column":29},"end":{"line":59,"column":30}},"loc":{"start":{"line":60,"column":16},"end":{"line":60,"column":29}}},"7":{"name":"(anonymous_8)","decl":{"start":{"line":79,"column":21},"end":{"line":79,"column":27}},"loc":{"start":{"line":79,"column":27},"end":{"line":79,"column":null}}},"8":{"name":"(anonymous_9)","decl":{"start":{"line":115,"column":31},"end":{"line":115,"column":32}},"loc":{"start":{"line":116,"column":20},"end":{"line":116,"column":40}}}},"branchMap":{"0":{"loc":{"start":{"line":41,"column":17},"end":{"line":41,"column":null}},"type":"cond-expr","locations":[{"start":{"line":41,"column":40},"end":{"line":41,"column":51}},{"start":{"line":41,"column":54},"end":{"line":41,"column":null}}]},"1":{"loc":{"start":{"line":47,"column":4},"end":{"line":47,"column":null}},"type":"if","locations":[{"start":{"line":47,"column":4},"end":{"line":47,"column":null}}]},"2":{"loc":{"start":{"line":50,"column":2},"end":{"line":71,"column":null}},"type":"if","locations":[{"start":{"line":50,"column":2},"end":{"line":71,"column":null}}]},"3":{"loc":{"start":{"line":73,"column":2},"end":{"line":87,"column":null}},"type":"if","locations":[{"start":{"line":73,"column":2},"end":{"line":87,"column":null}}]},"4":{"loc":{"start":{"line":73,"column":6},"end":{"line":73,"column":24}},"type":"binary-expr","locations":[{"start":{"line":73,"column":6},"end":{"line":73,"column":15}},{"start":{"line":73,"column":15},"end":{"line":73,"column":24}}]},"5":{"loc":{"start":{"line":77,"column":47},"end":{"line":77,"column":null}},"type":"binary-expr","locations":[{"start":{"line":77,"column":47},"end":{"line":77,"column":56}},{"start":{"line":77,"column":56},"end":{"line":77,"column":null}}]},"6":{"loc":{"start":{"line":93,"column":9},"end":{"line":93,"column":27}},"type":"binary-expr","locations":[{"start":{"line":93,"column":9},"end":{"line":93,"column":27}}]},"7":{"loc":{"start":{"line":107,"column":16},"end":{"line":114,"column":17}},"type":"cond-expr","locations":[{"start":{"line":107,"column":16},"end":{"line":114,"column":17}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0},"b":{"0":[0,0],"1":[0],"2":[0],"3":[0],"4":[0,0],"5":[0,0],"6":[0],"7":[0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/courses/[courseId]/documents/[documentId]/preview/page.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/courses/[courseId]/documents/[documentId]/preview/page.tsx","statementMap":{"0":{"start":{"line":9,"column":24},"end":{"line":9,"column":null}},"1":{"start":{"line":3,"column":49},"end":{"line":3,"column":null}},"2":{"start":{"line":4,"column":37},"end":{"line":4,"column":null}},"3":{"start":{"line":5,"column":27},"end":{"line":5,"column":null}},"4":{"start":{"line":6,"column":39},"end":{"line":6,"column":null}},"5":{"start":{"line":10,"column":17},"end":{"line":10,"column":null}},"6":{"start":{"line":11,"column":17},"end":{"line":11,"column":null}},"7":{"start":{"line":12,"column":19},"end":{"line":12,"column":34}},"8":{"start":{"line":13,"column":21},"end":{"line":13,"column":38}},"9":{"start":{"line":14,"column":28},"end":{"line":14,"column":null}},"10":{"start":{"line":15,"column":23},"end":{"line":15,"column":null}},"11":{"start":{"line":17,"column":32},"end":{"line":17,"column":null}},"12":{"start":{"line":18,"column":32},"end":{"line":18,"column":null}},"13":{"start":{"line":19,"column":28},"end":{"line":19,"column":null}},"14":{"start":{"line":21,"column":15},"end":{"line":31,"column":null}},"15":{"start":{"line":22,"column":4},"end":{"line":30,"column":null}},"16":{"start":{"line":23,"column":6},"end":{"line":23,"column":null}},"17":{"start":{"line":24,"column":19},"end":{"line":24,"column":null}},"18":{"start":{"line":25,"column":6},"end":{"line":25,"column":null}},"19":{"start":{"line":27,"column":6},"end":{"line":27,"column":null}},"20":{"start":{"line":29,"column":6},"end":{"line":29,"column":null}},"21":{"start":{"line":33,"column":2},"end":{"line":35,"column":null}},"22":{"start":{"line":34,"column":4},"end":{"line":34,"column":null}},"23":{"start":{"line":37,"column":2},"end":{"line":47,"column":null}},"24":{"start":{"line":49,"column":2},"end":{"line":71,"column":null}},"25":{"start":{"line":62,"column":29},"end":{"line":62,"column":null}},"26":{"start":{"line":78,"column":25},"end":{"line":78,"column":null}},"27":{"start":{"line":120,"column":18},"end":{"line":120,"column":31}},"28":{"start":{"line":143,"column":18},"end":{"line":143,"column":31}}},"fnMap":{"0":{"name":"DocumentPreviewPage","decl":{"start":{"line":9,"column":24},"end":{"line":9,"column":null}},"loc":{"start":{"line":9,"column":24},"end":{"line":159,"column":null}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":21,"column":27},"end":{"line":21,"column":null}},"loc":{"start":{"line":21,"column":27},"end":{"line":31,"column":5}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":33,"column":12},"end":{"line":33,"column":null}},"loc":{"start":{"line":33,"column":12},"end":{"line":35,"column":5}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":62,"column":23},"end":{"line":62,"column":29}},"loc":{"start":{"line":62,"column":29},"end":{"line":62,"column":null}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":78,"column":19},"end":{"line":78,"column":25}},"loc":{"start":{"line":78,"column":25},"end":{"line":78,"column":null}}},"5":{"name":"(anonymous_6)","decl":{"start":{"line":119,"column":38},"end":{"line":119,"column":39}},"loc":{"start":{"line":120,"column":18},"end":{"line":120,"column":31}}},"6":{"name":"(anonymous_7)","decl":{"start":{"line":142,"column":42},"end":{"line":142,"column":43}},"loc":{"start":{"line":143,"column":18},"end":{"line":143,"column":31}}}},"branchMap":{"0":{"loc":{"start":{"line":27,"column":15},"end":{"line":27,"column":null}},"type":"cond-expr","locations":[{"start":{"line":27,"column":38},"end":{"line":27,"column":49}},{"start":{"line":27,"column":52},"end":{"line":27,"column":null}}]},"1":{"loc":{"start":{"line":37,"column":2},"end":{"line":47,"column":null}},"type":"if","locations":[{"start":{"line":37,"column":2},"end":{"line":47,"column":null}}]},"2":{"loc":{"start":{"line":49,"column":2},"end":{"line":71,"column":null}},"type":"if","locations":[{"start":{"line":49,"column":2},"end":{"line":71,"column":null}}]},"3":{"loc":{"start":{"line":49,"column":6},"end":{"line":49,"column":25}},"type":"binary-expr","locations":[{"start":{"line":49,"column":6},"end":{"line":49,"column":15}},{"start":{"line":49,"column":15},"end":{"line":49,"column":25}}]},"4":{"loc":{"start":{"line":53,"column":47},"end":{"line":53,"column":null}},"type":"binary-expr","locations":[{"start":{"line":53,"column":47},"end":{"line":53,"column":56}},{"start":{"line":53,"column":56},"end":{"line":53,"column":null}}]},"5":{"loc":{"start":{"line":88,"column":11},"end":{"line":88,"column":null}},"type":"binary-expr","locations":[{"start":{"line":88,"column":11},"end":{"line":88,"column":null}}]},"6":{"loc":{"start":{"line":89,"column":74},"end":{"line":89,"column":null}},"type":"cond-expr","locations":[{"start":{"line":89,"column":100},"end":{"line":89,"column":106}},{"start":{"line":89,"column":106},"end":{"line":89,"column":null}}]},"7":{"loc":{"start":{"line":102,"column":14},"end":{"line":106,"column":15}},"type":"cond-expr","locations":[{"start":{"line":102,"column":14},"end":{"line":106,"column":15}}]},"8":{"loc":{"start":{"line":118,"column":14},"end":{"line":129,"column":15}},"type":"cond-expr","locations":[{"start":{"line":118,"column":14},"end":{"line":129,"column":15}}]},"9":{"loc":{"start":{"line":117,"column":13},"end":{"line":117,"column":null}},"type":"binary-expr","locations":[{"start":{"line":117,"column":13},"end":{"line":117,"column":29}},{"start":{"line":117,"column":33},"end":{"line":117,"column":null}}]},"10":{"loc":{"start":{"line":141,"column":14},"end":{"line":152,"column":15}},"type":"cond-expr","locations":[{"start":{"line":141,"column":14},"end":{"line":152,"column":15}}]},"11":{"loc":{"start":{"line":140,"column":13},"end":{"line":140,"column":null}},"type":"binary-expr","locations":[{"start":{"line":140,"column":13},"end":{"line":140,"column":33}},{"start":{"line":140,"column":37},"end":{"line":140,"column":null}}]},"12":{"loc":{"start":{"line":146,"column":23},"end":{"line":146,"column":null}},"type":"cond-expr","locations":[{"start":{"line":146,"column":51},"end":{"line":146,"column":59}},{"start":{"line":146,"column":59},"end":{"line":146,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0},"b":{"0":[0,0],"1":[0],"2":[0],"3":[0,0],"4":[0,0],"5":[0],"6":[0,0],"7":[0],"8":[0],"9":[0,0],"10":[0],"11":[0,0],"12":[0,0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/courses/[courseId]/study/page.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/courses/[courseId]/study/page.tsx","statementMap":{"0":{"start":{"line":11,"column":24},"end":{"line":11,"column":null}},"1":{"start":{"line":3,"column":36},"end":{"line":3,"column":null}},"2":{"start":{"line":4,"column":26},"end":{"line":4,"column":null}},"3":{"start":{"line":5,"column":27},"end":{"line":5,"column":null}},"4":{"start":{"line":6,"column":39},"end":{"line":6,"column":null}},"5":{"start":{"line":7,"column":26},"end":{"line":7,"column":null}},"6":{"start":{"line":8,"column":27},"end":{"line":8,"column":null}},"7":{"start":{"line":9,"column":27},"end":{"line":9,"column":null}},"8":{"start":{"line":12,"column":17},"end":{"line":12,"column":null}},"9":{"start":{"line":13,"column":19},"end":{"line":13,"column":34}},"10":{"start":{"line":14,"column":28},"end":{"line":14,"column":null}},"11":{"start":{"line":15,"column":23},"end":{"line":15,"column":null}},"12":{"start":{"line":17,"column":30},"end":{"line":17,"column":null}},"13":{"start":{"line":18,"column":32},"end":{"line":18,"column":null}},"14":{"start":{"line":20,"column":2},"end":{"line":32,"column":null}},"15":{"start":{"line":22,"column":6},"end":{"line":29,"column":null}},"16":{"start":{"line":23,"column":21},"end":{"line":23,"column":null}},"17":{"start":{"line":24,"column":8},"end":{"line":24,"column":null}},"18":{"start":{"line":28,"column":8},"end":{"line":28,"column":null}},"19":{"start":{"line":31,"column":4},"end":{"line":31,"column":null}},"20":{"start":{"line":31,"column":18},"end":{"line":31,"column":null}},"21":{"start":{"line":34,"column":2},"end":{"line":40,"column":null}}},"fnMap":{"0":{"name":"StudyPage","decl":{"start":{"line":11,"column":24},"end":{"line":11,"column":null}},"loc":{"start":{"line":11,"column":24},"end":{"line":51,"column":null}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":20,"column":12},"end":{"line":20,"column":null}},"loc":{"start":{"line":20,"column":12},"end":{"line":32,"column":5}}},"2":{"name":"load","decl":{"start":{"line":21,"column":19},"end":{"line":21,"column":null}},"loc":{"start":{"line":21,"column":19},"end":{"line":30,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":31,"column":4},"end":{"line":31,"column":null}},"type":"if","locations":[{"start":{"line":31,"column":4},"end":{"line":31,"column":null}}]},"1":{"loc":{"start":{"line":34,"column":2},"end":{"line":40,"column":null}},"type":"if","locations":[{"start":{"line":34,"column":2},"end":{"line":40,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0},"f":{"0":0,"1":0,"2":0},"b":{"0":[0],"1":[0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/dashboard/page.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/app/dashboard/page.tsx","statementMap":{"0":{"start":{"line":9,"column":24},"end":{"line":9,"column":null}},"1":{"start":{"line":3,"column":36},"end":{"line":3,"column":null}},"2":{"start":{"line":4,"column":36},"end":{"line":4,"column":null}},"3":{"start":{"line":5,"column":26},"end":{"line":5,"column":null}},"4":{"start":{"line":6,"column":17},"end":{"line":6,"column":null}},"5":{"start":{"line":7,"column":40},"end":{"line":7,"column":null}},"6":{"start":{"line":10,"column":36},"end":{"line":10,"column":null}},"7":{"start":{"line":11,"column":17},"end":{"line":11,"column":null}},"8":{"start":{"line":12,"column":32},"end":{"line":12,"column":null}},"9":{"start":{"line":13,"column":46},"end":{"line":13,"column":null}},"10":{"start":{"line":15,"column":2},"end":{"line":30,"column":null}},"11":{"start":{"line":16,"column":4},"end":{"line":16,"column":null}},"12":{"start":{"line":16,"column":36},"end":{"line":16,"column":null}},"13":{"start":{"line":19,"column":6},"end":{"line":26,"column":null}},"14":{"start":{"line":20,"column":21},"end":{"line":20,"column":null}},"15":{"start":{"line":21,"column":8},"end":{"line":21,"column":null}},"16":{"start":{"line":25,"column":8},"end":{"line":25,"column":null}},"17":{"start":{"line":29,"column":4},"end":{"line":29,"column":null}},"18":{"start":{"line":32,"column":2},"end":{"line":41,"column":null}},"19":{"start":{"line":43,"column":2},"end":{"line":46,"column":null}},"20":{"start":{"line":44,"column":4},"end":{"line":44,"column":null}},"21":{"start":{"line":45,"column":4},"end":{"line":45,"column":null}},"22":{"start":{"line":48,"column":24},"end":{"line":50,"column":null}},"23":{"start":{"line":49,"column":4},"end":{"line":49,"column":null}}},"fnMap":{"0":{"name":"DashboardPage","decl":{"start":{"line":9,"column":24},"end":{"line":9,"column":null}},"loc":{"start":{"line":9,"column":24},"end":{"line":141,"column":null}}},"1":{"name":"(anonymous_3)","decl":{"start":{"line":15,"column":12},"end":{"line":15,"column":null}},"loc":{"start":{"line":15,"column":12},"end":{"line":30,"column":5}}},"2":{"name":"fetchCourses","decl":{"start":{"line":18,"column":19},"end":{"line":18,"column":null}},"loc":{"start":{"line":18,"column":19},"end":{"line":27,"column":null}}},"3":{"name":"(anonymous_5)","decl":{"start":{"line":48,"column":24},"end":{"line":48,"column":null}},"loc":{"start":{"line":48,"column":24},"end":{"line":50,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":16,"column":4},"end":{"line":16,"column":null}},"type":"if","locations":[{"start":{"line":16,"column":4},"end":{"line":16,"column":null}}]},"1":{"loc":{"start":{"line":32,"column":2},"end":{"line":41,"column":null}},"type":"if","locations":[{"start":{"line":32,"column":2},"end":{"line":41,"column":null}}]},"2":{"loc":{"start":{"line":43,"column":2},"end":{"line":46,"column":null}},"type":"if","locations":[{"start":{"line":43,"column":2},"end":{"line":46,"column":null}}]},"3":{"loc":{"start":{"line":72,"column":23},"end":{"line":72,"column":82}},"type":"binary-expr","locations":[{"start":{"line":72,"column":23},"end":{"line":72,"column":61}},{"start":{"line":72,"column":61},"end":{"line":72,"column":82}}]},"4":{"loc":{"start":{"line":87,"column":21},"end":{"line":87,"column":null}},"type":"binary-expr","locations":[{"start":{"line":87,"column":21},"end":{"line":87,"column":60}},{"start":{"line":87,"column":60},"end":{"line":87,"column":null}}]},"5":{"loc":{"start":{"line":93,"column":21},"end":{"line":93,"column":null}},"type":"binary-expr","locations":[{"start":{"line":93,"column":21},"end":{"line":93,"column":53}},{"start":{"line":93,"column":53},"end":{"line":93,"column":null}}]},"6":{"loc":{"start":{"line":106,"column":21},"end":{"line":109,"column":36}},"type":"cond-expr","locations":[{"start":{"line":107,"column":22},"end":{"line":109,"column":30}},{"start":{"line":109,"column":22},"end":{"line":109,"column":36}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0},"f":{"0":0,"1":0,"2":0,"3":0},"b":{"0":[0],"1":[0],"2":[0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/courses/CourseCard.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/courses/CourseCard.tsx","statementMap":{"0":{"start":{"line":10,"column":16},"end":{"line":10,"column":27}},"1":{"start":{"line":3,"column":17},"end":{"line":3,"column":null}}},"fnMap":{"0":{"name":"CourseCard","decl":{"start":{"line":10,"column":16},"end":{"line":10,"column":27}},"loc":{"start":{"line":10,"column":54},"end":{"line":45,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":22,"column":13},"end":{"line":22,"column":31}},"type":"binary-expr","locations":[{"start":{"line":22,"column":13},"end":{"line":22,"column":31}}]}},"s":{"0":0,"1":0},"f":{"0":0},"b":{"0":[0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/courses/DocumentList.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/courses/DocumentList.tsx","statementMap":{"0":{"start":{"line":37,"column":16},"end":{"line":37,"column":29}},"1":{"start":{"line":3,"column":57},"end":{"line":3,"column":null}},"2":{"start":{"line":4,"column":36},"end":{"line":4,"column":null}},"3":{"start":{"line":6,"column":36},"end":{"line":6,"column":null}},"4":{"start":{"line":7,"column":40},"end":{"line":7,"column":null}},"5":{"start":{"line":16,"column":30},"end":{"line":16,"column":null}},"6":{"start":{"line":19,"column":2},"end":{"line":19,"column":null}},"7":{"start":{"line":19,"column":20},"end":{"line":19,"column":null}},"8":{"start":{"line":20,"column":2},"end":{"line":20,"column":null}},"9":{"start":{"line":20,"column":27},"end":{"line":20,"column":null}},"10":{"start":{"line":21,"column":2},"end":{"line":21,"column":null}},"11":{"start":{"line":25,"column":2},"end":{"line":34,"column":null}},"12":{"start":{"line":26,"column":4},"end":{"line":31,"column":null}},"13":{"start":{"line":33,"column":4},"end":{"line":33,"column":null}},"14":{"start":{"line":43,"column":36},"end":{"line":43,"column":null}},"15":{"start":{"line":44,"column":32},"end":{"line":44,"column":null}},"16":{"start":{"line":45,"column":28},"end":{"line":45,"column":null}},"17":{"start":{"line":46,"column":38},"end":{"line":46,"column":null}},"18":{"start":{"line":47,"column":38},"end":{"line":47,"column":null}},"19":{"start":{"line":48,"column":18},"end":{"line":48,"column":null}},"20":{"start":{"line":50,"column":25},"end":{"line":69,"column":null}},"21":{"start":{"line":52,"column":6},"end":{"line":67,"column":null}},"22":{"start":{"line":53,"column":8},"end":{"line":53,"column":null}},"23":{"start":{"line":53,"column":21},"end":{"line":53,"column":null}},"24":{"start":{"line":54,"column":21},"end":{"line":54,"column":null}},"25":{"start":{"line":55,"column":8},"end":{"line":55,"column":null}},"26":{"start":{"line":57,"column":24},"end":{"line":57,"column":null}},"27":{"start":{"line":58,"column":8},"end":{"line":63,"column":null}},"28":{"start":{"line":59,"column":10},"end":{"line":59,"column":null}},"29":{"start":{"line":60,"column":10},"end":{"line":60,"column":null}},"30":{"start":{"line":61,"column":15},"end":{"line":63,"column":null}},"31":{"start":{"line":62,"column":10},"end":{"line":62,"column":null}},"32":{"start":{"line":65,"column":8},"end":{"line":65,"column":null}},"33":{"start":{"line":66,"column":8},"end":{"line":66,"column":null}},"34":{"start":{"line":72,"column":2},"end":{"line":74,"column":null}},"35":{"start":{"line":73,"column":4},"end":{"line":73,"column":null}},"36":{"start":{"line":76,"column":2},"end":{"line":84,"column":null}},"37":{"start":{"line":77,"column":26},"end":{"line":77,"column":null}},"38":{"start":{"line":77,"column":48},"end":{"line":77,"column":61}},"39":{"start":{"line":78,"column":4},"end":{"line":80,"column":null}},"40":{"start":{"line":79,"column":6},"end":{"line":79,"column":null}},"41":{"start":{"line":79,"column":42},"end":{"line":79,"column":64}},"42":{"start":{"line":81,"column":4},"end":{"line":83,"column":null}},"43":{"start":{"line":82,"column":6},"end":{"line":82,"column":null}},"44":{"start":{"line":82,"column":27},"end":{"line":82,"column":null}},"45":{"start":{"line":87,"column":4},"end":{"line":87,"column":null}},"46":{"start":{"line":88,"column":4},"end":{"line":88,"column":null}},"47":{"start":{"line":92,"column":4},"end":{"line":92,"column":null}},"48":{"start":{"line":92,"column":29},"end":{"line":92,"column":null}},"49":{"start":{"line":95,"column":2},"end":{"line":109,"column":null}},"50":{"start":{"line":99,"column":10},"end":{"line":99,"column":23}},"51":{"start":{"line":111,"column":2},"end":{"line":123,"column":null}},"52":{"start":{"line":116,"column":25},"end":{"line":116,"column":null}},"53":{"start":{"line":125,"column":2},"end":{"line":145,"column":null}},"54":{"start":{"line":178,"column":29},"end":{"line":178,"column":50}},"55":{"start":{"line":179,"column":10},"end":{"line":180,"column":29}},"56":{"start":{"line":183,"column":31},"end":{"line":183,"column":null}}},"fnMap":{"0":{"name":"formatFileSize","decl":{"start":{"line":18,"column":9},"end":{"line":18,"column":24}},"loc":{"start":{"line":18,"column":37},"end":{"line":22,"column":null}}},"1":{"name":"formatTime","decl":{"start":{"line":24,"column":9},"end":{"line":24,"column":20}},"loc":{"start":{"line":24,"column":31},"end":{"line":35,"column":null}}},"2":{"name":"DocumentList","decl":{"start":{"line":37,"column":16},"end":{"line":37,"column":29}},"loc":{"start":{"line":42,"column":20},"end":{"line":241,"column":null}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":51,"column":4},"end":{"line":51,"column":11}},"loc":{"start":{"line":51,"column":25},"end":{"line":68,"column":null}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":72,"column":12},"end":{"line":72,"column":null}},"loc":{"start":{"line":72,"column":12},"end":{"line":74,"column":5}}},"5":{"name":"(anonymous_6)","decl":{"start":{"line":76,"column":12},"end":{"line":76,"column":null}},"loc":{"start":{"line":76,"column":12},"end":{"line":84,"column":5}}},"6":{"name":"(anonymous_7)","decl":{"start":{"line":77,"column":41},"end":{"line":77,"column":42}},"loc":{"start":{"line":77,"column":48},"end":{"line":77,"column":61}}},"7":{"name":"(anonymous_8)","decl":{"start":{"line":79,"column":36},"end":{"line":79,"column":42}},"loc":{"start":{"line":79,"column":42},"end":{"line":79,"column":64}}},"8":{"name":"(anonymous_9)","decl":{"start":{"line":81,"column":11},"end":{"line":81,"column":null}},"loc":{"start":{"line":81,"column":11},"end":{"line":83,"column":null}}},"9":{"name":"handleRefresh","decl":{"start":{"line":86,"column":11},"end":{"line":86,"column":null}},"loc":{"start":{"line":86,"column":11},"end":{"line":89,"column":null}}},"10":{"name":"toggleExpand","decl":{"start":{"line":91,"column":11},"end":{"line":91,"column":24}},"loc":{"start":{"line":91,"column":34},"end":{"line":93,"column":null}}},"11":{"name":"(anonymous_12)","decl":{"start":{"line":92,"column":18},"end":{"line":92,"column":19}},"loc":{"start":{"line":92,"column":29},"end":{"line":92,"column":null}}},"12":{"name":"(anonymous_13)","decl":{"start":{"line":98,"column":23},"end":{"line":98,"column":24}},"loc":{"start":{"line":99,"column":10},"end":{"line":99,"column":23}}},"13":{"name":"(anonymous_14)","decl":{"start":{"line":116,"column":19},"end":{"line":116,"column":25}},"loc":{"start":{"line":116,"column":25},"end":{"line":116,"column":null}}},"14":{"name":"(anonymous_15)","decl":{"start":{"line":177,"column":23},"end":{"line":177,"column":24}},"loc":{"start":{"line":177,"column":24},"end":{"line":237,"column":null}}},"15":{"name":"(anonymous_16)","decl":{"start":{"line":183,"column":25},"end":{"line":183,"column":31}},"loc":{"start":{"line":183,"column":31},"end":{"line":183,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":19,"column":2},"end":{"line":19,"column":null}},"type":"if","locations":[{"start":{"line":19,"column":2},"end":{"line":19,"column":null}}]},"1":{"loc":{"start":{"line":20,"column":2},"end":{"line":20,"column":null}},"type":"if","locations":[{"start":{"line":20,"column":2},"end":{"line":20,"column":null}}]},"2":{"loc":{"start":{"line":40,"column":2},"end":{"line":40,"column":16}},"type":"default-arg","locations":[{"start":{"line":40,"column":15},"end":{"line":40,"column":16}}]},"3":{"loc":{"start":{"line":51,"column":11},"end":{"line":51,"column":25}},"type":"default-arg","locations":[{"start":{"line":51,"column":20},"end":{"line":51,"column":25}}]},"4":{"loc":{"start":{"line":53,"column":8},"end":{"line":53,"column":null}},"type":"if","locations":[{"start":{"line":53,"column":8},"end":{"line":53,"column":null}}]},"5":{"loc":{"start":{"line":57,"column":24},"end":{"line":57,"column":null}},"type":"cond-expr","locations":[{"start":{"line":57,"column":47},"end":{"line":57,"column":58}},{"start":{"line":57,"column":61},"end":{"line":57,"column":null}}]},"6":{"loc":{"start":{"line":58,"column":8},"end":{"line":63,"column":null}},"type":"if","locations":[{"start":{"line":58,"column":8},"end":{"line":63,"column":null}},{"start":{"line":61,"column":15},"end":{"line":63,"column":null}}]},"7":{"loc":{"start":{"line":58,"column":12},"end":{"line":58,"column":96}},"type":"binary-expr","locations":[{"start":{"line":58,"column":12},"end":{"line":58,"column":56}},{"start":{"line":58,"column":56},"end":{"line":58,"column":96}}]},"8":{"loc":{"start":{"line":61,"column":15},"end":{"line":63,"column":null}},"type":"if","locations":[{"start":{"line":61,"column":15},"end":{"line":63,"column":null}}]},"9":{"loc":{"start":{"line":78,"column":4},"end":{"line":80,"column":null}},"type":"if","locations":[{"start":{"line":78,"column":4},"end":{"line":80,"column":null}}]},"10":{"loc":{"start":{"line":82,"column":6},"end":{"line":82,"column":null}},"type":"if","locations":[{"start":{"line":82,"column":6},"end":{"line":82,"column":null}}]},"11":{"loc":{"start":{"line":92,"column":29},"end":{"line":92,"column":null}},"type":"cond-expr","locations":[{"start":{"line":92,"column":43},"end":{"line":92,"column":50}},{"start":{"line":92,"column":50},"end":{"line":92,"column":null}}]},"12":{"loc":{"start":{"line":95,"column":2},"end":{"line":109,"column":null}},"type":"if","locations":[{"start":{"line":95,"column":2},"end":{"line":109,"column":null}}]},"13":{"loc":{"start":{"line":111,"column":2},"end":{"line":123,"column":null}},"type":"if","locations":[{"start":{"line":111,"column":2},"end":{"line":123,"column":null}}]},"14":{"loc":{"start":{"line":125,"column":2},"end":{"line":145,"column":null}},"type":"if","locations":[{"start":{"line":125,"column":2},"end":{"line":145,"column":null}}]},"15":{"loc":{"start":{"line":151,"column":38},"end":{"line":151,"column":null}},"type":"cond-expr","locations":[{"start":{"line":151,"column":63},"end":{"line":151,"column":69}},{"start":{"line":151,"column":69},"end":{"line":151,"column":null}}]},"16":{"loc":{"start":{"line":160,"column":38},"end":{"line":160,"column":71}},"type":"cond-expr","locations":[{"start":{"line":160,"column":51},"end":{"line":160,"column":68}},{"start":{"line":160,"column":68},"end":{"line":160,"column":71}}]},"17":{"loc":{"start":{"line":172,"column":11},"end":{"line":172,"column":null}},"type":"cond-expr","locations":[{"start":{"line":172,"column":24},"end":{"line":172,"column":42}},{"start":{"line":172,"column":42},"end":{"line":172,"column":null}}]},"18":{"loc":{"start":{"line":190,"column":96},"end":{"line":190,"column":126}},"type":"cond-expr","locations":[{"start":{"line":190,"column":109},"end":{"line":190,"column":123}},{"start":{"line":190,"column":123},"end":{"line":190,"column":126}}]},"19":{"loc":{"start":{"line":216,"column":21},"end":{"line":216,"column":47}},"type":"binary-expr","locations":[{"start":{"line":216,"column":21},"end":{"line":216,"column":47}},{"start":{"line":216,"column":47},"end":{"line":216,"column":63}}]},"20":{"loc":{"start":{"line":226,"column":15},"end":{"line":226,"column":null}},"type":"binary-expr","locations":[{"start":{"line":226,"column":15},"end":{"line":226,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0},"b":{"0":[0],"1":[0],"2":[0],"3":[0],"4":[0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0],"9":[0],"10":[0],"11":[0,0],"12":[0],"13":[0],"14":[0],"15":[0,0],"16":[0,0],"17":[0,0],"18":[0,0],"19":[0,0],"20":[0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/courses/ProcessingIndicator.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/courses/ProcessingIndicator.tsx","statementMap":{"0":{"start":{"line":49,"column":16},"end":{"line":49,"column":36}},"1":{"start":{"line":11,"column":104},"end":{"line":36,"column":null}},"2":{"start":{"line":38,"column":54},"end":{"line":47,"column":null}},"3":{"start":{"line":50,"column":17},"end":{"line":50,"column":38}},"4":{"start":{"line":51,"column":21},"end":{"line":51,"column":null}}},"fnMap":{"0":{"name":"ProcessingIndicator","decl":{"start":{"line":49,"column":16},"end":{"line":49,"column":36}},"loc":{"start":{"line":49,"column":95},"end":{"line":64,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":49,"column":53},"end":{"line":49,"column":67}},"type":"default-arg","locations":[{"start":{"line":49,"column":65},"end":{"line":49,"column":67}}]},"1":{"loc":{"start":{"line":51,"column":21},"end":{"line":51,"column":null}},"type":"cond-expr","locations":[{"start":{"line":51,"column":70},"end":{"line":51,"column":89}},{"start":{"line":51,"column":92},"end":{"line":51,"column":null}}]},"2":{"loc":{"start":{"line":51,"column":21},"end":{"line":51,"column":70}},"type":"binary-expr","locations":[{"start":{"line":51,"column":21},"end":{"line":51,"column":30}},{"start":{"line":51,"column":30},"end":{"line":51,"column":50}},{"start":{"line":51,"column":50},"end":{"line":51,"column":70}}]},"3":{"loc":{"start":{"line":59,"column":7},"end":{"line":59,"column":21}},"type":"binary-expr","locations":[{"start":{"line":59,"column":7},"end":{"line":59,"column":21}},{"start":{"line":59,"column":21},"end":{"line":59,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0},"f":{"0":0},"b":{"0":[0],"1":[0,0],"2":[0,0,0],"3":[0,0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/documents/DocumentProcessingPanel.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/documents/DocumentProcessingPanel.tsx","statementMap":{"0":{"start":{"line":22,"column":16},"end":{"line":22,"column":40}},"1":{"start":{"line":3,"column":49},"end":{"line":3,"column":null}},"2":{"start":{"line":4,"column":38},"end":{"line":4,"column":null}},"3":{"start":{"line":27,"column":30},"end":{"line":27,"column":null}},"4":{"start":{"line":28,"column":32},"end":{"line":28,"column":null}},"5":{"start":{"line":29,"column":28},"end":{"line":29,"column":null}},"6":{"start":{"line":31,"column":15},"end":{"line":41,"column":null}},"7":{"start":{"line":32,"column":4},"end":{"line":40,"column":null}},"8":{"start":{"line":33,"column":6},"end":{"line":33,"column":null}},"9":{"start":{"line":34,"column":19},"end":{"line":34,"column":null}},"10":{"start":{"line":35,"column":6},"end":{"line":35,"column":null}},"11":{"start":{"line":37,"column":6},"end":{"line":37,"column":null}},"12":{"start":{"line":39,"column":6},"end":{"line":39,"column":null}},"13":{"start":{"line":43,"column":2},"end":{"line":45,"column":null}},"14":{"start":{"line":44,"column":4},"end":{"line":44,"column":null}},"15":{"start":{"line":47,"column":2},"end":{"line":55,"column":null}},"16":{"start":{"line":57,"column":2},"end":{"line":66,"column":null}},"17":{"start":{"line":68,"column":2},"end":{"line":68,"column":null}},"18":{"start":{"line":68,"column":15},"end":{"line":68,"column":null}},"19":{"start":{"line":97,"column":25},"end":{"line":97,"column":null}}},"fnMap":{"0":{"name":"DetailRow","decl":{"start":{"line":13,"column":9},"end":{"line":13,"column":19}},"loc":{"start":{"line":13,"column":78},"end":{"line":20,"column":null}}},"1":{"name":"DocumentProcessingPanel","decl":{"start":{"line":22,"column":16},"end":{"line":22,"column":40}},"loc":{"start":{"line":26,"column":31},"end":{"line":108,"column":null}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":31,"column":27},"end":{"line":31,"column":null}},"loc":{"start":{"line":31,"column":27},"end":{"line":41,"column":5}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":43,"column":12},"end":{"line":43,"column":null}},"loc":{"start":{"line":43,"column":12},"end":{"line":45,"column":5}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":97,"column":19},"end":{"line":97,"column":25}},"loc":{"start":{"line":97,"column":25},"end":{"line":97,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":17,"column":56},"end":{"line":17,"column":65}},"type":"binary-expr","locations":[{"start":{"line":17,"column":56},"end":{"line":17,"column":65}}]},"1":{"loc":{"start":{"line":37,"column":15},"end":{"line":37,"column":null}},"type":"cond-expr","locations":[{"start":{"line":37,"column":38},"end":{"line":37,"column":49}},{"start":{"line":37,"column":52},"end":{"line":37,"column":null}}]},"2":{"loc":{"start":{"line":47,"column":2},"end":{"line":55,"column":null}},"type":"if","locations":[{"start":{"line":47,"column":2},"end":{"line":55,"column":null}}]},"3":{"loc":{"start":{"line":57,"column":2},"end":{"line":66,"column":null}},"type":"if","locations":[{"start":{"line":57,"column":2},"end":{"line":66,"column":null}}]},"4":{"loc":{"start":{"line":68,"column":2},"end":{"line":68,"column":null}},"type":"if","locations":[{"start":{"line":68,"column":2},"end":{"line":68,"column":null}}]},"5":{"loc":{"start":{"line":79,"column":9},"end":{"line":79,"column":28}},"type":"binary-expr","locations":[{"start":{"line":79,"column":9},"end":{"line":79,"column":28}}]},"6":{"loc":{"start":{"line":85,"column":9},"end":{"line":85,"column":34}},"type":"binary-expr","locations":[{"start":{"line":85,"column":9},"end":{"line":85,"column":34}}]},"7":{"loc":{"start":{"line":95,"column":7},"end":{"line":95,"column":24}},"type":"binary-expr","locations":[{"start":{"line":95,"column":7},"end":{"line":95,"column":24}},{"start":{"line":95,"column":24},"end":{"line":95,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0},"b":{"0":[0],"1":[0,0],"2":[0],"3":[0],"4":[0],"5":[0],"6":[0],"7":[0,0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/documents/DocumentRow.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/documents/DocumentRow.tsx","statementMap":{"0":{"start":{"line":20,"column":16},"end":{"line":20,"column":28}},"1":{"start":{"line":3,"column":25},"end":{"line":3,"column":null}},"2":{"start":{"line":5,"column":31},"end":{"line":5,"column":null}},"3":{"start":{"line":6,"column":36},"end":{"line":6,"column":null}},"4":{"start":{"line":15,"column":2},"end":{"line":15,"column":null}},"5":{"start":{"line":15,"column":20},"end":{"line":15,"column":null}},"6":{"start":{"line":16,"column":2},"end":{"line":16,"column":null}},"7":{"start":{"line":16,"column":27},"end":{"line":16,"column":null}},"8":{"start":{"line":17,"column":2},"end":{"line":17,"column":null}},"9":{"start":{"line":21,"column":34},"end":{"line":21,"column":null}},"10":{"start":{"line":24,"column":4},"end":{"line":24,"column":null}},"11":{"start":{"line":24,"column":47},"end":{"line":24,"column":null}},"12":{"start":{"line":25,"column":4},"end":{"line":25,"column":null}},"13":{"start":{"line":26,"column":4},"end":{"line":31,"column":null}},"14":{"start":{"line":27,"column":6},"end":{"line":27,"column":null}},"15":{"start":{"line":28,"column":6},"end":{"line":28,"column":null}},"16":{"start":{"line":30,"column":6},"end":{"line":30,"column":null}}},"fnMap":{"0":{"name":"formatFileSize","decl":{"start":{"line":14,"column":9},"end":{"line":14,"column":24}},"loc":{"start":{"line":14,"column":37},"end":{"line":18,"column":null}}},"1":{"name":"DocumentRow","decl":{"start":{"line":20,"column":16},"end":{"line":20,"column":28}},"loc":{"start":{"line":20,"column":87},"end":{"line":58,"column":null}}},"2":{"name":"handleDelete","decl":{"start":{"line":23,"column":17},"end":{"line":23,"column":null}},"loc":{"start":{"line":23,"column":17},"end":{"line":32,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":15,"column":2},"end":{"line":15,"column":null}},"type":"if","locations":[{"start":{"line":15,"column":2},"end":{"line":15,"column":null}}]},"1":{"loc":{"start":{"line":16,"column":2},"end":{"line":16,"column":null}},"type":"if","locations":[{"start":{"line":16,"column":2},"end":{"line":16,"column":null}}]},"2":{"loc":{"start":{"line":24,"column":4},"end":{"line":24,"column":null}},"type":"if","locations":[{"start":{"line":24,"column":4},"end":{"line":24,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0},"f":{"0":0,"1":0,"2":0},"b":{"0":[0],"1":[0],"2":[0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/documents/DocumentUpload.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/documents/DocumentUpload.tsx","statementMap":{"0":{"start":{"line":18,"column":16},"end":{"line":18,"column":31}},"1":{"start":{"line":3,"column":46},"end":{"line":3,"column":null}},"2":{"start":{"line":4,"column":58},"end":{"line":4,"column":null}},"3":{"start":{"line":19,"column":26},"end":{"line":19,"column":null}},"4":{"start":{"line":20,"column":38},"end":{"line":20,"column":null}},"5":{"start":{"line":21,"column":19},"end":{"line":21,"column":null}},"6":{"start":{"line":23,"column":22},"end":{"line":69,"column":null}},"7":{"start":{"line":25,"column":24},"end":{"line":25,"column":null}},"8":{"start":{"line":26,"column":6},"end":{"line":26,"column":null}},"9":{"start":{"line":26,"column":34},"end":{"line":26,"column":null}},"10":{"start":{"line":28,"column":35},"end":{"line":31,"column":null}},"11":{"start":{"line":28,"column":60},"end":{"line":31,"column":null}},"12":{"start":{"line":33,"column":6},"end":{"line":33,"column":null}},"13":{"start":{"line":33,"column":24},"end":{"line":33,"column":null}},"14":{"start":{"line":35,"column":6},"end":{"line":67,"column":null}},"15":{"start":{"line":35,"column":19},"end":{"line":35,"column":22}},"16":{"start":{"line":36,"column":21},"end":{"line":36,"column":33}},"17":{"start":{"line":37,"column":25},"end":{"line":37,"column":null}},"18":{"start":{"line":39,"column":8},"end":{"line":66,"column":null}},"19":{"start":{"line":40,"column":22},"end":{"line":40,"column":null}},"20":{"start":{"line":42,"column":10},"end":{"line":46,"column":null}},"21":{"start":{"line":43,"column":28},"end":{"line":43,"column":null}},"22":{"start":{"line":44,"column":12},"end":{"line":44,"column":null}},"23":{"start":{"line":44,"column":35},"end":{"line":44,"column":null}},"24":{"start":{"line":45,"column":12},"end":{"line":45,"column":null}},"25":{"start":{"line":48,"column":10},"end":{"line":48,"column":null}},"26":{"start":{"line":50,"column":10},"end":{"line":54,"column":null}},"27":{"start":{"line":51,"column":28},"end":{"line":51,"column":null}},"28":{"start":{"line":52,"column":12},"end":{"line":52,"column":null}},"29":{"start":{"line":52,"column":35},"end":{"line":52,"column":null}},"30":{"start":{"line":53,"column":12},"end":{"line":53,"column":null}},"31":{"start":{"line":56,"column":10},"end":{"line":56,"column":null}},"32":{"start":{"line":58,"column":26},"end":{"line":58,"column":null}},"33":{"start":{"line":59,"column":10},"end":{"line":64,"column":null}},"34":{"start":{"line":60,"column":28},"end":{"line":60,"column":null}},"35":{"start":{"line":61,"column":12},"end":{"line":62,"column":null}},"36":{"start":{"line":62,"column":14},"end":{"line":62,"column":null}},"37":{"start":{"line":63,"column":12},"end":{"line":63,"column":null}},"38":{"start":{"line":65,"column":10},"end":{"line":65,"column":null}},"39":{"start":{"line":72,"column":17},"end":{"line":80,"column":null}},"40":{"start":{"line":74,"column":6},"end":{"line":74,"column":null}},"41":{"start":{"line":75,"column":6},"end":{"line":75,"column":null}},"42":{"start":{"line":76,"column":6},"end":{"line":78,"column":null}},"43":{"start":{"line":77,"column":8},"end":{"line":77,"column":null}},"44":{"start":{"line":83,"column":21},"end":{"line":83,"column":null}},"45":{"start":{"line":83,"column":40},"end":{"line":83,"column":null}},"46":{"start":{"line":84,"column":20},"end":{"line":84,"column":null}},"47":{"start":{"line":84,"column":39},"end":{"line":84,"column":null}},"48":{"start":{"line":90,"column":10},"end":{"line":90,"column":null}},"49":{"start":{"line":91,"column":10},"end":{"line":91,"column":null}},"50":{"start":{"line":93,"column":27},"end":{"line":93,"column":null}},"51":{"start":{"line":95,"column":23},"end":{"line":95,"column":null}},"52":{"start":{"line":109,"column":12},"end":{"line":109,"column":null}},"53":{"start":{"line":109,"column":32},"end":{"line":109,"column":null}},"54":{"start":{"line":110,"column":12},"end":{"line":110,"column":null}},"55":{"start":{"line":125,"column":12},"end":{"line":125,"column":25}},"56":{"start":{"line":140,"column":12},"end":{"line":140,"column":25}}},"fnMap":{"0":{"name":"DocumentUpload","decl":{"start":{"line":18,"column":16},"end":{"line":18,"column":31}},"loc":{"start":{"line":18,"column":95},"end":{"line":152,"column":null}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":24,"column":4},"end":{"line":24,"column":11}},"loc":{"start":{"line":24,"column":11},"end":{"line":68,"column":null}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":28,"column":49},"end":{"line":28,"column":50}},"loc":{"start":{"line":28,"column":60},"end":{"line":31,"column":null}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":33,"column":14},"end":{"line":33,"column":15}},"loc":{"start":{"line":33,"column":24},"end":{"line":33,"column":null}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":42,"column":18},"end":{"line":42,"column":19}},"loc":{"start":{"line":42,"column":19},"end":{"line":46,"column":null}}},"5":{"name":"(anonymous_6)","decl":{"start":{"line":50,"column":18},"end":{"line":50,"column":19}},"loc":{"start":{"line":50,"column":19},"end":{"line":54,"column":null}}},"6":{"name":"(anonymous_7)","decl":{"start":{"line":59,"column":18},"end":{"line":59,"column":19}},"loc":{"start":{"line":59,"column":19},"end":{"line":64,"column":null}}},"7":{"name":"(anonymous_8)","decl":{"start":{"line":73,"column":4},"end":{"line":73,"column":5}},"loc":{"start":{"line":73,"column":5},"end":{"line":79,"column":null}}},"8":{"name":"(anonymous_9)","decl":{"start":{"line":83,"column":33},"end":{"line":83,"column":34}},"loc":{"start":{"line":83,"column":40},"end":{"line":83,"column":null}}},"9":{"name":"(anonymous_10)","decl":{"start":{"line":84,"column":32},"end":{"line":84,"column":33}},"loc":{"start":{"line":84,"column":39},"end":{"line":84,"column":null}}},"10":{"name":"(anonymous_11)","decl":{"start":{"line":89,"column":20},"end":{"line":89,"column":21}},"loc":{"start":{"line":89,"column":21},"end":{"line":92,"column":null}}},"11":{"name":"(anonymous_12)","decl":{"start":{"line":93,"column":21},"end":{"line":93,"column":27}},"loc":{"start":{"line":93,"column":27},"end":{"line":93,"column":null}}},"12":{"name":"(anonymous_13)","decl":{"start":{"line":95,"column":17},"end":{"line":95,"column":23}},"loc":{"start":{"line":95,"column":23},"end":{"line":95,"column":null}}},"13":{"name":"(anonymous_14)","decl":{"start":{"line":108,"column":20},"end":{"line":108,"column":21}},"loc":{"start":{"line":108,"column":21},"end":{"line":111,"column":null}}},"14":{"name":"(anonymous_15)","decl":{"start":{"line":124,"column":26},"end":{"line":124,"column":27}},"loc":{"start":{"line":125,"column":12},"end":{"line":125,"column":25}}},"15":{"name":"(anonymous_16)","decl":{"start":{"line":139,"column":25},"end":{"line":139,"column":26}},"loc":{"start":{"line":140,"column":12},"end":{"line":140,"column":25}}}},"branchMap":{"0":{"loc":{"start":{"line":26,"column":6},"end":{"line":26,"column":null}},"type":"if","locations":[{"start":{"line":26,"column":6},"end":{"line":26,"column":null}}]},"1":{"loc":{"start":{"line":44,"column":12},"end":{"line":44,"column":null}},"type":"if","locations":[{"start":{"line":44,"column":12},"end":{"line":44,"column":null}}]},"2":{"loc":{"start":{"line":52,"column":12},"end":{"line":52,"column":null}},"type":"if","locations":[{"start":{"line":52,"column":12},"end":{"line":52,"column":null}}]},"3":{"loc":{"start":{"line":58,"column":26},"end":{"line":58,"column":null}},"type":"cond-expr","locations":[{"start":{"line":58,"column":49},"end":{"line":58,"column":60}},{"start":{"line":58,"column":63},"end":{"line":58,"column":null}}]},"4":{"loc":{"start":{"line":61,"column":12},"end":{"line":62,"column":null}},"type":"if","locations":[{"start":{"line":61,"column":12},"end":{"line":62,"column":null}}]},"5":{"loc":{"start":{"line":76,"column":6},"end":{"line":78,"column":null}},"type":"if","locations":[{"start":{"line":76,"column":6},"end":{"line":78,"column":null}}]},"6":{"loc":{"start":{"line":83,"column":40},"end":{"line":83,"column":null}},"type":"binary-expr","locations":[{"start":{"line":83,"column":40},"end":{"line":83,"column":70}},{"start":{"line":83,"column":70},"end":{"line":83,"column":null}}]},"7":{"loc":{"start":{"line":97,"column":10},"end":{"line":99,"column":null}},"type":"cond-expr","locations":[{"start":{"line":98,"column":14},"end":{"line":98,"column":null}},{"start":{"line":99,"column":14},"end":{"line":99,"column":null}}]},"8":{"loc":{"start":{"line":109,"column":12},"end":{"line":109,"column":null}},"type":"if","locations":[{"start":{"line":109,"column":12},"end":{"line":109,"column":null}}]},"9":{"loc":{"start":{"line":122,"column":7},"end":{"line":122,"column":null}},"type":"binary-expr","locations":[{"start":{"line":122,"column":7},"end":{"line":122,"column":null}}]},"10":{"loc":{"start":{"line":137,"column":7},"end":{"line":137,"column":null}},"type":"binary-expr","locations":[{"start":{"line":137,"column":7},"end":{"line":137,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0},"b":{"0":[0],"1":[0],"2":[0],"3":[0,0],"4":[0],"5":[0],"6":[0,0],"7":[0,0],"8":[0],"9":[0],"10":[0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/providers/AuthProvider.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/providers/AuthProvider.tsx","statementMap":{"0":{"start":{"line":18,"column":16},"end":{"line":18,"column":28}},"1":{"start":{"line":22,"column":0},"end":{"line":22,"column":15}},"2":{"start":{"line":7,"column":32},"end":{"line":7,"column":null}},"3":{"start":{"line":22,"column":15},"end":{"line":22,"column":28}}},"fnMap":{"0":{"name":"AuthProvider","decl":{"start":{"line":18,"column":16},"end":{"line":18,"column":28}},"loc":{"start":{"line":18,"column":60},"end":{"line":20,"column":null}}}},"branchMap":{},"s":{"0":0,"1":0,"2":0,"3":0},"f":{"0":0},"b":{}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/study/OutputPane.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/study/OutputPane.tsx","statementMap":{"0":{"start":{"line":3,"column":16},"end":{"line":3,"column":null}}},"fnMap":{"0":{"name":"OutputPane","decl":{"start":{"line":3,"column":16},"end":{"line":3,"column":null}},"loc":{"start":{"line":3,"column":16},"end":{"line":38,"column":null}}}},"branchMap":{},"s":{"0":0},"f":{"0":0},"b":{}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/study/SourcePane.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/study/SourcePane.tsx","statementMap":{"0":{"start":{"line":7,"column":16},"end":{"line":7,"column":27}}},"fnMap":{"0":{"name":"SourcePane","decl":{"start":{"line":7,"column":16},"end":{"line":7,"column":27}},"loc":{"start":{"line":7,"column":59},"end":{"line":45,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":14,"column":9},"end":{"line":14,"column":null}},"type":"binary-expr","locations":[{"start":{"line":14,"column":9},"end":{"line":14,"column":null}}]}},"s":{"0":0},"f":{"0":0},"b":{"0":[0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/study/SplitPane.tsx": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/components/study/SplitPane.tsx","statementMap":{"0":{"start":{"line":13,"column":16},"end":{"line":13,"column":26}},"1":{"start":{"line":3,"column":62},"end":{"line":3,"column":null}},"2":{"start":{"line":20,"column":40},"end":{"line":20,"column":null}},"3":{"start":{"line":21,"column":23},"end":{"line":21,"column":null}},"4":{"start":{"line":22,"column":19},"end":{"line":22,"column":null}},"5":{"start":{"line":24,"column":22},"end":{"line":49,"column":null}},"6":{"start":{"line":26,"column":6},"end":{"line":26,"column":null}},"7":{"start":{"line":27,"column":6},"end":{"line":27,"column":null}},"8":{"start":{"line":29,"column":26},"end":{"line":34,"column":null}},"9":{"start":{"line":30,"column":8},"end":{"line":30,"column":null}},"10":{"start":{"line":30,"column":56},"end":{"line":30,"column":null}},"11":{"start":{"line":31,"column":21},"end":{"line":31,"column":null}},"12":{"start":{"line":32,"column":24},"end":{"line":32,"column":null}},"13":{"start":{"line":33,"column":8},"end":{"line":33,"column":null}},"14":{"start":{"line":36,"column":24},"end":{"line":42,"column":null}},"15":{"start":{"line":37,"column":8},"end":{"line":37,"column":null}},"16":{"start":{"line":38,"column":8},"end":{"line":38,"column":null}},"17":{"start":{"line":39,"column":8},"end":{"line":39,"column":null}},"18":{"start":{"line":40,"column":8},"end":{"line":40,"column":null}},"19":{"start":{"line":41,"column":8},"end":{"line":41,"column":null}},"20":{"start":{"line":44,"column":6},"end":{"line":44,"column":null}},"21":{"start":{"line":45,"column":6},"end":{"line":45,"column":null}},"22":{"start":{"line":46,"column":6},"end":{"line":46,"column":null}},"23":{"start":{"line":47,"column":6},"end":{"line":47,"column":null}}},"fnMap":{"0":{"name":"SplitPane","decl":{"start":{"line":13,"column":16},"end":{"line":13,"column":26}},"loc":{"start":{"line":19,"column":17},"end":{"line":71,"column":null}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":25,"column":4},"end":{"line":25,"column":5}},"loc":{"start":{"line":25,"column":5},"end":{"line":48,"column":null}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":29,"column":26},"end":{"line":29,"column":27}},"loc":{"start":{"line":29,"column":27},"end":{"line":34,"column":null}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":36,"column":24},"end":{"line":36,"column":null}},"loc":{"start":{"line":36,"column":24},"end":{"line":42,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":16,"column":2},"end":{"line":16,"column":25}},"type":"default-arg","locations":[{"start":{"line":16,"column":23},"end":{"line":16,"column":25}}]},"1":{"loc":{"start":{"line":17,"column":2},"end":{"line":17,"column":21}},"type":"default-arg","locations":[{"start":{"line":17,"column":19},"end":{"line":17,"column":21}}]},"2":{"loc":{"start":{"line":18,"column":2},"end":{"line":18,"column":21}},"type":"default-arg","locations":[{"start":{"line":18,"column":19},"end":{"line":18,"column":21}}]},"3":{"loc":{"start":{"line":30,"column":8},"end":{"line":30,"column":null}},"type":"if","locations":[{"start":{"line":30,"column":8},"end":{"line":30,"column":null}}]},"4":{"loc":{"start":{"line":30,"column":12},"end":{"line":30,"column":54}},"type":"binary-expr","locations":[{"start":{"line":30,"column":12},"end":{"line":30,"column":29}},{"start":{"line":30,"column":33},"end":{"line":30,"column":54}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0},"f":{"0":0,"1":0,"2":0,"3":0},"b":{"0":[0],"1":[0],"2":[0],"3":[0],"4":[0,0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/api.ts": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/api.ts","statementMap":{"0":{"start":{"line":7,"column":13},"end":{"line":7,"column":21}},"1":{"start":{"line":35,"column":22},"end":{"line":35,"column":30}},"2":{"start":{"line":2,"column":2},"end":{"line":5,"column":null}},"3":{"start":{"line":13,"column":4},"end":{"line":13,"column":null}},"4":{"start":{"line":9,"column":11},"end":{"line":9,"column":25}},"5":{"start":{"line":11,"column":11},"end":{"line":11,"column":44}},"6":{"start":{"line":14,"column":4},"end":{"line":14,"column":null}},"7":{"start":{"line":24,"column":2},"end":{"line":31,"column":null}},"8":{"start":{"line":25,"column":22},"end":{"line":25,"column":null}},"9":{"start":{"line":25,"column":57},"end":{"line":25,"column":null}},"10":{"start":{"line":26,"column":4},"end":{"line":29,"column":null}},"11":{"start":{"line":32,"column":2},"end":{"line":32,"column":null}},"12":{"start":{"line":39,"column":65},"end":{"line":39,"column":null}},"13":{"start":{"line":41,"column":42},"end":{"line":43,"column":null}},"14":{"start":{"line":45,"column":2},"end":{"line":47,"column":null}},"15":{"start":{"line":46,"column":4},"end":{"line":46,"column":null}},"16":{"start":{"line":49,"column":2},"end":{"line":51,"column":null}},"17":{"start":{"line":50,"column":4},"end":{"line":50,"column":null}},"18":{"start":{"line":53,"column":19},"end":{"line":57,"column":null}},"19":{"start":{"line":59,"column":2},"end":{"line":59,"column":null}}},"fnMap":{"0":{"name":"(anonymous_3)","decl":{"start":{"line":8,"column":2},"end":{"line":8,"column":null}},"loc":{"start":{"line":12,"column":4},"end":{"line":15,"column":null}}},"1":{"name":"handleResponse","decl":{"start":{"line":23,"column":15},"end":{"line":23,"column":33}},"loc":{"start":{"line":23,"column":51},"end":{"line":33,"column":null}}},"2":{"name":"(anonymous_5)","decl":{"start":{"line":25,"column":50},"end":{"line":25,"column":57}},"loc":{"start":{"line":25,"column":57},"end":{"line":25,"column":null}}},"3":{"name":"apiFetch","decl":{"start":{"line":35,"column":22},"end":{"line":35,"column":30}},"loc":{"start":{"line":37,"column":28},"end":{"line":60,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":2,"column":2},"end":{"line":5,"column":null}},"type":"binary-expr","locations":[{"start":{"line":2,"column":2},"end":{"line":2,"column":38}},{"start":{"line":3,"column":3},"end":{"line":5,"column":32}}]},"1":{"loc":{"start":{"line":3,"column":3},"end":{"line":5,"column":32}},"type":"cond-expr","locations":[{"start":{"line":4,"column":6},"end":{"line":4,"column":46}},{"start":{"line":5,"column":6},"end":{"line":5,"column":32}}]},"2":{"loc":{"start":{"line":24,"column":2},"end":{"line":31,"column":null}},"type":"if","locations":[{"start":{"line":24,"column":2},"end":{"line":31,"column":null}}]},"3":{"loc":{"start":{"line":28,"column":6},"end":{"line":28,"column":84}},"type":"binary-expr","locations":[{"start":{"line":28,"column":6},"end":{"line":28,"column":22}},{"start":{"line":28,"column":26},"end":{"line":28,"column":43}},{"start":{"line":28,"column":47},"end":{"line":28,"column":84}}]},"4":{"loc":{"start":{"line":37,"column":2},"end":{"line":37,"column":28}},"type":"default-arg","locations":[{"start":{"line":37,"column":26},"end":{"line":37,"column":28}}]},"5":{"loc":{"start":{"line":45,"column":2},"end":{"line":47,"column":null}},"type":"if","locations":[{"start":{"line":45,"column":2},"end":{"line":47,"column":null}}]},"6":{"loc":{"start":{"line":49,"column":2},"end":{"line":51,"column":null}},"type":"if","locations":[{"start":{"line":49,"column":2},"end":{"line":51,"column":null}}]},"7":{"loc":{"start":{"line":49,"column":6},"end":{"line":49,"column":57}},"type":"binary-expr","locations":[{"start":{"line":49,"column":6},"end":{"line":49,"column":28}},{"start":{"line":49,"column":28},"end":{"line":49,"column":57}}]},"8":{"loc":{"start":{"line":56,"column":10},"end":{"line":56,"column":null}},"type":"cond-expr","locations":[{"start":{"line":56,"column":37},"end":{"line":56,"column":44}},{"start":{"line":56,"column":44},"end":{"line":56,"column":null}}]},"9":{"loc":{"start":{"line":56,"column":44},"end":{"line":56,"column":null}},"type":"cond-expr","locations":[{"start":{"line":56,"column":65},"end":{"line":56,"column":88}},{"start":{"line":56,"column":88},"end":{"line":56,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0},"f":{"0":0,"1":0,"2":0,"3":0},"b":{"0":[0,0],"1":[0,0],"2":[0],"3":[0,0,0],"4":[0],"5":[0],"6":[0],"7":[0,0],"8":[0,0],"9":[0,0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/api/adapters.ts": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/api/adapters.ts","statementMap":{"0":{"start":{"line":43,"column":16},"end":{"line":43,"column":36}},"1":{"start":{"line":27,"column":16},"end":{"line":27,"column":33}},"2":{"start":{"line":72,"column":16},"end":{"line":72,"column":37}},"3":{"start":{"line":13,"column":2},"end":{"line":20,"column":null}},"4":{"start":{"line":14,"column":16},"end":{"line":14,"column":34}},"5":{"start":{"line":15,"column":4},"end":{"line":15,"column":null}},"6":{"start":{"line":15,"column":23},"end":{"line":15,"column":null}},"7":{"start":{"line":16,"column":4},"end":{"line":16,"column":null}},"8":{"start":{"line":16,"column":81},"end":{"line":16,"column":null}},"9":{"start":{"line":17,"column":4},"end":{"line":17,"column":null}},"10":{"start":{"line":17,"column":79},"end":{"line":17,"column":null}},"11":{"start":{"line":18,"column":4},"end":{"line":18,"column":null}},"12":{"start":{"line":18,"column":25},"end":{"line":18,"column":null}},"13":{"start":{"line":19,"column":4},"end":{"line":19,"column":null}},"14":{"start":{"line":19,"column":13},"end":{"line":19,"column":null}},"15":{"start":{"line":21,"column":14},"end":{"line":21,"column":null}},"16":{"start":{"line":22,"column":2},"end":{"line":22,"column":null}},"17":{"start":{"line":25,"column":55},"end":{"line":25,"column":null}},"18":{"start":{"line":28,"column":2},"end":{"line":40,"column":null}},"19":{"start":{"line":44,"column":59},"end":{"line":44,"column":null}},"20":{"start":{"line":45,"column":2},"end":{"line":51,"column":null}},"21":{"start":{"line":46,"column":4},"end":{"line":50,"column":null}},"22":{"start":{"line":47,"column":6},"end":{"line":47,"column":null}},"23":{"start":{"line":49,"column":6},"end":{"line":49,"column":null}},"24":{"start":{"line":53,"column":2},"end":{"line":69,"column":null}},"25":{"start":{"line":73,"column":2},"end":{"line":80,"column":null}}},"fnMap":{"0":{"name":"mimeToLabel","decl":{"start":{"line":12,"column":9},"end":{"line":12,"column":21}},"loc":{"start":{"line":12,"column":58},"end":{"line":23,"column":null}}},"1":{"name":"toDocumentListRow","decl":{"start":{"line":27,"column":16},"end":{"line":27,"column":33}},"loc":{"start":{"line":27,"column":59},"end":{"line":41,"column":null}}},"2":{"name":"toDocumentDetailView","decl":{"start":{"line":43,"column":16},"end":{"line":43,"column":36}},"loc":{"start":{"line":43,"column":60},"end":{"line":70,"column":null}}},"3":{"name":"toDocumentPreviewView","decl":{"start":{"line":72,"column":16},"end":{"line":72,"column":37}},"loc":{"start":{"line":72,"column":62},"end":{"line":81,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":13,"column":2},"end":{"line":20,"column":null}},"type":"if","locations":[{"start":{"line":13,"column":2},"end":{"line":20,"column":null}}]},"1":{"loc":{"start":{"line":15,"column":4},"end":{"line":15,"column":null}},"type":"if","locations":[{"start":{"line":15,"column":4},"end":{"line":15,"column":null}}]},"2":{"loc":{"start":{"line":16,"column":4},"end":{"line":16,"column":null}},"type":"if","locations":[{"start":{"line":16,"column":4},"end":{"line":16,"column":null}}]},"3":{"loc":{"start":{"line":17,"column":4},"end":{"line":17,"column":null}},"type":"if","locations":[{"start":{"line":17,"column":4},"end":{"line":17,"column":null}}]},"4":{"loc":{"start":{"line":18,"column":4},"end":{"line":18,"column":null}},"type":"if","locations":[{"start":{"line":18,"column":4},"end":{"line":18,"column":null}}]},"5":{"loc":{"start":{"line":19,"column":4},"end":{"line":19,"column":null}},"type":"if","locations":[{"start":{"line":19,"column":4},"end":{"line":19,"column":null}}]},"6":{"loc":{"start":{"line":22,"column":9},"end":{"line":22,"column":null}},"type":"binary-expr","locations":[{"start":{"line":22,"column":9},"end":{"line":22,"column":16}},{"start":{"line":22,"column":16},"end":{"line":22,"column":null}}]},"7":{"loc":{"start":{"line":45,"column":2},"end":{"line":51,"column":null}},"type":"if","locations":[{"start":{"line":45,"column":2},"end":{"line":51,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0},"f":{"0":0,"1":0,"2":0,"3":0},"b":{"0":[0],"1":[0],"2":[0],"3":[0],"4":[0],"5":[0],"6":[0,0],"7":[0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/api/courses.ts": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/api/courses.ts","statementMap":{"0":{"start":{"line":28,"column":22},"end":{"line":28,"column":34}},"1":{"start":{"line":14,"column":22},"end":{"line":14,"column":33}},"2":{"start":{"line":21,"column":22},"end":{"line":21,"column":40}},"3":{"start":{"line":4,"column":22},"end":{"line":4,"column":34}},"4":{"start":{"line":1,"column":25},"end":{"line":1,"column":null}},"5":{"start":{"line":9,"column":2},"end":{"line":11,"column":null}},"6":{"start":{"line":18,"column":2},"end":{"line":18,"column":null}},"7":{"start":{"line":25,"column":2},"end":{"line":25,"column":null}},"8":{"start":{"line":32,"column":2},"end":{"line":36,"column":null}}},"fnMap":{"0":{"name":"fetchCourses","decl":{"start":{"line":4,"column":22},"end":{"line":4,"column":34}},"loc":{"start":{"line":7,"column":22},"end":{"line":12,"column":null}}},"1":{"name":"fetchCourse","decl":{"start":{"line":14,"column":22},"end":{"line":14,"column":33}},"loc":{"start":{"line":16,"column":22},"end":{"line":19,"column":null}}},"2":{"name":"fetchCourseLessons","decl":{"start":{"line":21,"column":22},"end":{"line":21,"column":40}},"loc":{"start":{"line":23,"column":22},"end":{"line":26,"column":null}}},"3":{"name":"createCourse","decl":{"start":{"line":28,"column":22},"end":{"line":28,"column":34}},"loc":{"start":{"line":30,"column":22},"end":{"line":37,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":5,"column":2},"end":{"line":5,"column":10}},"type":"default-arg","locations":[{"start":{"line":5,"column":9},"end":{"line":5,"column":10}}]},"1":{"loc":{"start":{"line":6,"column":2},"end":{"line":6,"column":13}},"type":"default-arg","locations":[{"start":{"line":6,"column":10},"end":{"line":6,"column":13}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0},"f":{"0":0,"1":0,"2":0,"3":0},"b":{"0":[0],"1":[0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/api/documents.ts": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/api/documents.ts","statementMap":{"0":{"start":{"line":65,"column":22},"end":{"line":65,"column":36}},"1":{"start":{"line":33,"column":22},"end":{"line":33,"column":41}},"2":{"start":{"line":42,"column":22},"end":{"line":42,"column":42}},"3":{"start":{"line":24,"column":22},"end":{"line":24,"column":41}},"4":{"start":{"line":15,"column":22},"end":{"line":15,"column":40}},"5":{"start":{"line":85,"column":22},"end":{"line":85,"column":43}},"6":{"start":{"line":77,"column":22},"end":{"line":77,"column":41}},"7":{"start":{"line":93,"column":22},"end":{"line":93,"column":44}},"8":{"start":{"line":103,"column":22},"end":{"line":103,"column":47}},"9":{"start":{"line":51,"column":22},"end":{"line":51,"column":36}},"10":{"start":{"line":1,"column":35},"end":{"line":1,"column":null}},"11":{"start":{"line":11,"column":79},"end":{"line":11,"column":null}},"12":{"start":{"line":19,"column":2},"end":{"line":21,"column":null}},"13":{"start":{"line":28,"column":2},"end":{"line":30,"column":null}},"14":{"start":{"line":37,"column":2},"end":{"line":39,"column":null}},"15":{"start":{"line":46,"column":2},"end":{"line":48,"column":null}},"16":{"start":{"line":56,"column":19},"end":{"line":56,"column":null}},"17":{"start":{"line":57,"column":2},"end":{"line":57,"column":null}},"18":{"start":{"line":58,"column":2},"end":{"line":62,"column":null}},"19":{"start":{"line":69,"column":2},"end":{"line":72,"column":null}},"20":{"start":{"line":81,"column":16},"end":{"line":81,"column":null}},"21":{"start":{"line":82,"column":2},"end":{"line":82,"column":null}},"22":{"start":{"line":89,"column":15},"end":{"line":89,"column":null}},"23":{"start":{"line":90,"column":2},"end":{"line":90,"column":null}},"24":{"start":{"line":97,"column":15},"end":{"line":97,"column":null}},"25":{"start":{"line":98,"column":2},"end":{"line":98,"column":null}},"26":{"start":{"line":109,"column":2},"end":{"line":123,"column":null}},"27":{"start":{"line":109,"column":15},"end":{"line":109,"column":18}},"28":{"start":{"line":110,"column":4},"end":{"line":121,"column":null}},"29":{"start":{"line":111,"column":21},"end":{"line":111,"column":null}},"30":{"start":{"line":112,"column":6},"end":{"line":114,"column":null}},"31":{"start":{"line":113,"column":8},"end":{"line":113,"column":null}},"32":{"start":{"line":116,"column":6},"end":{"line":120,"column":null}},"33":{"start":{"line":119,"column":8},"end":{"line":119,"column":null}},"34":{"start":{"line":122,"column":4},"end":{"line":122,"column":null}},"35":{"start":{"line":122,"column":35},"end":{"line":122,"column":null}},"36":{"start":{"line":124,"column":2},"end":{"line":124,"column":null}}},"fnMap":{"0":{"name":"fetchDocumentsList","decl":{"start":{"line":15,"column":22},"end":{"line":15,"column":40}},"loc":{"start":{"line":17,"column":22},"end":{"line":22,"column":null}}},"1":{"name":"fetchDocumentStatus","decl":{"start":{"line":24,"column":22},"end":{"line":24,"column":41}},"loc":{"start":{"line":26,"column":22},"end":{"line":31,"column":null}}},"2":{"name":"fetchDocumentDetail","decl":{"start":{"line":33,"column":22},"end":{"line":33,"column":41}},"loc":{"start":{"line":35,"column":22},"end":{"line":40,"column":null}}},"3":{"name":"fetchDocumentPreview","decl":{"start":{"line":42,"column":22},"end":{"line":42,"column":42}},"loc":{"start":{"line":44,"column":22},"end":{"line":49,"column":null}}},"4":{"name":"uploadDocument","decl":{"start":{"line":51,"column":22},"end":{"line":51,"column":36}},"loc":{"start":{"line":54,"column":22},"end":{"line":63,"column":null}}},"5":{"name":"deleteDocument","decl":{"start":{"line":65,"column":22},"end":{"line":65,"column":36}},"loc":{"start":{"line":67,"column":22},"end":{"line":73,"column":null}}},"6":{"name":"getDocumentListRows","decl":{"start":{"line":77,"column":22},"end":{"line":77,"column":41}},"loc":{"start":{"line":79,"column":22},"end":{"line":83,"column":null}}},"7":{"name":"getDocumentDetailView","decl":{"start":{"line":85,"column":22},"end":{"line":85,"column":43}},"loc":{"start":{"line":87,"column":22},"end":{"line":91,"column":null}}},"8":{"name":"getDocumentPreviewView","decl":{"start":{"line":93,"column":22},"end":{"line":93,"column":44}},"loc":{"start":{"line":95,"column":22},"end":{"line":99,"column":null}}},"9":{"name":"pollDocumentUntilTerminal","decl":{"start":{"line":103,"column":22},"end":{"line":103,"column":47}},"loc":{"start":{"line":107,"column":18},"end":{"line":125,"column":null}}},"10":{"name":"(anonymous_21)","decl":{"start":{"line":122,"column":22},"end":{"line":122,"column":23}},"loc":{"start":{"line":122,"column":35},"end":{"line":122,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":106,"column":2},"end":{"line":106,"column":19}},"type":"default-arg","locations":[{"start":{"line":106,"column":15},"end":{"line":106,"column":19}}]},"1":{"loc":{"start":{"line":107,"column":2},"end":{"line":107,"column":18}},"type":"default-arg","locations":[{"start":{"line":107,"column":16},"end":{"line":107,"column":18}}]},"2":{"loc":{"start":{"line":112,"column":6},"end":{"line":114,"column":null}},"type":"if","locations":[{"start":{"line":112,"column":6},"end":{"line":114,"column":null}}]},"3":{"loc":{"start":{"line":112,"column":10},"end":{"line":112,"column":66}},"type":"binary-expr","locations":[{"start":{"line":112,"column":10},"end":{"line":112,"column":39}},{"start":{"line":112,"column":39},"end":{"line":112,"column":66}}]},"4":{"loc":{"start":{"line":116,"column":6},"end":{"line":120,"column":null}},"type":"if","locations":[{"start":{"line":116,"column":6},"end":{"line":120,"column":null}},{"start":{"line":118,"column":13},"end":{"line":120,"column":null}}]},"5":{"loc":{"start":{"line":116,"column":10},"end":{"line":116,"column":56}},"type":"binary-expr","locations":[{"start":{"line":116,"column":10},"end":{"line":116,"column":33}},{"start":{"line":116,"column":37},"end":{"line":116,"column":56}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0},"b":{"0":[0],"1":[0],"2":[0],"3":[0,0],"4":[0,0],"5":[0,0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/api/index.ts": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/api/index.ts","statementMap":{"0":{"start":{"line":1,"column":14},"end":{"line":1,"column":null}},"1":{"start":{"line":2,"column":14},"end":{"line":2,"column":null}},"2":{"start":{"line":3,"column":14},"end":{"line":3,"column":null}},"3":{"start":{"line":4,"column":14},"end":{"line":4,"column":null}}},"fnMap":{},"branchMap":{},"s":{"0":0,"1":0,"2":0,"3":0},"f":{},"b":{}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/auth/config.ts": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/auth/config.ts","statementMap":{"0":{"start":{"line":6,"column":13},"end":{"line":6,"column":40}},"1":{"start":{"line":2,"column":32},"end":{"line":2,"column":null}},"2":{"start":{"line":4,"column":16},"end":{"line":4,"column":null}},"3":{"start":{"line":6,"column":40},"end":{"line":83,"column":null}},"4":{"start":{"line":15,"column":8},"end":{"line":17,"column":null}},"5":{"start":{"line":16,"column":10},"end":{"line":16,"column":null}},"6":{"start":{"line":19,"column":8},"end":{"line":50,"column":null}},"7":{"start":{"line":20,"column":22},"end":{"line":27,"column":null}},"8":{"start":{"line":29,"column":10},"end":{"line":32,"column":null}},"9":{"start":{"line":30,"column":26},"end":{"line":30,"column":null}},"10":{"start":{"line":30,"column":56},"end":{"line":30,"column":null}},"11":{"start":{"line":31,"column":12},"end":{"line":31,"column":null}},"12":{"start":{"line":34,"column":23},"end":{"line":34,"column":null}},"13":{"start":{"line":36,"column":10},"end":{"line":44,"column":null}},"14":{"start":{"line":46,"column":10},"end":{"line":48,"column":null}},"15":{"start":{"line":47,"column":12},"end":{"line":47,"column":null}},"16":{"start":{"line":49,"column":10},"end":{"line":49,"column":null}},"17":{"start":{"line":56,"column":6},"end":{"line":61,"column":null}},"18":{"start":{"line":57,"column":8},"end":{"line":57,"column":null}},"19":{"start":{"line":58,"column":8},"end":{"line":58,"column":null}},"20":{"start":{"line":59,"column":8},"end":{"line":59,"column":null}},"21":{"start":{"line":60,"column":8},"end":{"line":60,"column":null}},"22":{"start":{"line":62,"column":6},"end":{"line":62,"column":null}},"23":{"start":{"line":65,"column":6},"end":{"line":70,"column":null}},"24":{"start":{"line":66,"column":9},"end":{"line":66,"column":null}},"25":{"start":{"line":67,"column":9},"end":{"line":67,"column":null}},"26":{"start":{"line":68,"column":9},"end":{"line":68,"column":null}},"27":{"start":{"line":69,"column":9},"end":{"line":69,"column":null}},"28":{"start":{"line":71,"column":6},"end":{"line":71,"column":null}}},"fnMap":{"0":{"name":"(anonymous_2)","decl":{"start":{"line":14,"column":6},"end":{"line":14,"column":12}},"loc":{"start":{"line":14,"column":33},"end":{"line":51,"column":null}}},"1":{"name":"(anonymous_3)","decl":{"start":{"line":30,"column":49},"end":{"line":30,"column":56}},"loc":{"start":{"line":30,"column":56},"end":{"line":30,"column":null}}},"2":{"name":"(anonymous_4)","decl":{"start":{"line":55,"column":4},"end":{"line":55,"column":10}},"loc":{"start":{"line":55,"column":29},"end":{"line":63,"column":null}}},"3":{"name":"(anonymous_5)","decl":{"start":{"line":64,"column":4},"end":{"line":64,"column":10}},"loc":{"start":{"line":64,"column":36},"end":{"line":72,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":4,"column":16},"end":{"line":4,"column":null}},"type":"binary-expr","locations":[{"start":{"line":4,"column":16},"end":{"line":4,"column":47}},{"start":{"line":4,"column":51},"end":{"line":4,"column":null}}]},"1":{"loc":{"start":{"line":15,"column":8},"end":{"line":17,"column":null}},"type":"if","locations":[{"start":{"line":15,"column":8},"end":{"line":17,"column":null}}]},"2":{"loc":{"start":{"line":15,"column":12},"end":{"line":15,"column":59}},"type":"binary-expr","locations":[{"start":{"line":15,"column":12},"end":{"line":15,"column":35}},{"start":{"line":15,"column":35},"end":{"line":15,"column":59}}]},"3":{"loc":{"start":{"line":29,"column":10},"end":{"line":32,"column":null}},"type":"if","locations":[{"start":{"line":29,"column":10},"end":{"line":32,"column":null}}]},"4":{"loc":{"start":{"line":31,"column":28},"end":{"line":31,"column":null}},"type":"binary-expr","locations":[{"start":{"line":31,"column":28},"end":{"line":31,"column":40}},{"start":{"line":31,"column":44},"end":{"line":31,"column":null}}]},"5":{"loc":{"start":{"line":37,"column":16},"end":{"line":37,"column":40}},"type":"binary-expr","locations":[{"start":{"line":37,"column":16},"end":{"line":37,"column":33}},{"start":{"line":37,"column":33},"end":{"line":37,"column":40}}]},"6":{"loc":{"start":{"line":38,"column":19},"end":{"line":38,"column":56}},"type":"binary-expr","locations":[{"start":{"line":38,"column":19},"end":{"line":38,"column":39}},{"start":{"line":38,"column":39},"end":{"line":38,"column":56}}]},"7":{"loc":{"start":{"line":39,"column":18},"end":{"line":39,"column":null}},"type":"binary-expr","locations":[{"start":{"line":39,"column":18},"end":{"line":39,"column":45}},{"start":{"line":39,"column":45},"end":{"line":39,"column":null}}]},"8":{"loc":{"start":{"line":40,"column":25},"end":{"line":40,"column":null}},"type":"binary-expr","locations":[{"start":{"line":40,"column":25},"end":{"line":40,"column":42}},{"start":{"line":40,"column":46},"end":{"line":40,"column":null}}]},"9":{"loc":{"start":{"line":41,"column":26},"end":{"line":41,"column":null}},"type":"binary-expr","locations":[{"start":{"line":41,"column":26},"end":{"line":41,"column":44}},{"start":{"line":41,"column":48},"end":{"line":41,"column":null}}]},"10":{"loc":{"start":{"line":42,"column":18},"end":{"line":42,"column":null}},"type":"binary-expr","locations":[{"start":{"line":42,"column":18},"end":{"line":42,"column":37}},{"start":{"line":42,"column":37},"end":{"line":42,"column":null}}]},"11":{"loc":{"start":{"line":43,"column":25},"end":{"line":43,"column":null}},"type":"binary-expr","locations":[{"start":{"line":43,"column":25},"end":{"line":43,"column":52}},{"start":{"line":43,"column":52},"end":{"line":43,"column":null}}]},"12":{"loc":{"start":{"line":46,"column":10},"end":{"line":48,"column":null}},"type":"if","locations":[{"start":{"line":46,"column":10},"end":{"line":48,"column":null}}]},"13":{"loc":{"start":{"line":56,"column":6},"end":{"line":61,"column":null}},"type":"if","locations":[{"start":{"line":56,"column":6},"end":{"line":61,"column":null}}]},"14":{"loc":{"start":{"line":65,"column":6},"end":{"line":70,"column":null}},"type":"if","locations":[{"start":{"line":65,"column":6},"end":{"line":70,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0},"f":{"0":0,"1":0,"2":0,"3":0},"b":{"0":[0,0],"1":[0],"2":[0,0],"3":[0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0],"13":[0],"14":[0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/middleware/auth-guard.ts": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/middleware/auth-guard.ts","statementMap":{"0":{"start":{"line":7,"column":22},"end":{"line":7,"column":36}},"1":{"start":{"line":32,"column":13},"end":{"line":32,"column":19}},"2":{"start":{"line":1,"column":29},"end":{"line":1,"column":null}},"3":{"start":{"line":2,"column":25},"end":{"line":2,"column":null}},"4":{"start":{"line":5,"column":21},"end":{"line":5,"column":null}},"5":{"start":{"line":8,"column":23},"end":{"line":8,"column":38}},"6":{"start":{"line":10,"column":19},"end":{"line":11,"column":null}},"7":{"start":{"line":11,"column":14},"end":{"line":11,"column":null}},"8":{"start":{"line":14,"column":2},"end":{"line":16,"column":null}},"9":{"start":{"line":15,"column":4},"end":{"line":15,"column":null}},"10":{"start":{"line":18,"column":16},"end":{"line":21,"column":null}},"11":{"start":{"line":23,"column":2},"end":{"line":27,"column":null}},"12":{"start":{"line":24,"column":21},"end":{"line":24,"column":null}},"13":{"start":{"line":25,"column":4},"end":{"line":25,"column":null}},"14":{"start":{"line":26,"column":4},"end":{"line":26,"column":null}},"15":{"start":{"line":29,"column":2},"end":{"line":29,"column":null}},"16":{"start":{"line":32,"column":22},"end":{"line":34,"column":null}}},"fnMap":{"0":{"name":"authMiddleware","decl":{"start":{"line":7,"column":22},"end":{"line":7,"column":36}},"loc":{"start":{"line":7,"column":57},"end":{"line":30,"column":null}}},"1":{"name":"(anonymous_4)","decl":{"start":{"line":11,"column":4},"end":{"line":11,"column":5}},"loc":{"start":{"line":11,"column":14},"end":{"line":11,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":11,"column":14},"end":{"line":11,"column":null}},"type":"binary-expr","locations":[{"start":{"line":11,"column":14},"end":{"line":11,"column":35}},{"start":{"line":11,"column":35},"end":{"line":11,"column":null}}]},"1":{"loc":{"start":{"line":14,"column":2},"end":{"line":16,"column":null}},"type":"if","locations":[{"start":{"line":14,"column":2},"end":{"line":16,"column":null}}]},"2":{"loc":{"start":{"line":14,"column":6},"end":{"line":14,"column":84}},"type":"binary-expr","locations":[{"start":{"line":14,"column":6},"end":{"line":14,"column":18}},{"start":{"line":14,"column":18},"end":{"line":14,"column":51}},{"start":{"line":14,"column":51},"end":{"line":14,"column":84}}]},"3":{"loc":{"start":{"line":23,"column":2},"end":{"line":27,"column":null}},"type":"if","locations":[{"start":{"line":23,"column":2},"end":{"line":27,"column":null}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0},"f":{"0":0,"1":0},"b":{"0":[0,0],"1":[0],"2":[0,0,0],"3":[0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/services/courses.ts": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/services/courses.ts","statementMap":{"0":{"start":{"line":29,"column":22},"end":{"line":29,"column":31}},"1":{"start":{"line":36,"column":22},"end":{"line":36,"column":38}},"2":{"start":{"line":19,"column":22},"end":{"line":19,"column":32}},"3":{"start":{"line":43,"column":22},"end":{"line":43,"column":31}},"4":{"start":{"line":1,"column":25},"end":{"line":1,"column":null}},"5":{"start":{"line":24,"column":2},"end":{"line":26,"column":null}},"6":{"start":{"line":33,"column":2},"end":{"line":33,"column":null}},"7":{"start":{"line":40,"column":2},"end":{"line":40,"column":null}},"8":{"start":{"line":47,"column":2},"end":{"line":47,"column":null}}},"fnMap":{"0":{"name":"getCourses","decl":{"start":{"line":19,"column":22},"end":{"line":19,"column":32}},"loc":{"start":{"line":22,"column":22},"end":{"line":27,"column":null}}},"1":{"name":"getCourse","decl":{"start":{"line":29,"column":22},"end":{"line":29,"column":31}},"loc":{"start":{"line":31,"column":22},"end":{"line":34,"column":null}}},"2":{"name":"getCourseLessons","decl":{"start":{"line":36,"column":22},"end":{"line":36,"column":38}},"loc":{"start":{"line":38,"column":22},"end":{"line":41,"column":null}}},"3":{"name":"getLesson","decl":{"start":{"line":43,"column":22},"end":{"line":43,"column":31}},"loc":{"start":{"line":45,"column":22},"end":{"line":48,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":20,"column":2},"end":{"line":20,"column":10}},"type":"default-arg","locations":[{"start":{"line":20,"column":9},"end":{"line":20,"column":10}}]},"1":{"loc":{"start":{"line":21,"column":2},"end":{"line":21,"column":13}},"type":"default-arg","locations":[{"start":{"line":21,"column":10},"end":{"line":21,"column":13}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0},"f":{"0":0,"1":0,"2":0,"3":0},"b":{"0":[0],"1":[0]}} -,"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/services/documents.ts": {"path":"/Users/lucavisconti/BP-Academy/bitcoin-academy/apps/web/src/lib/services/documents.ts","statementMap":{"0":{"start":{"line":54,"column":22},"end":{"line":54,"column":36}},"1":{"start":{"line":45,"column":22},"end":{"line":45,"column":39}},"2":{"start":{"line":21,"column":22},"end":{"line":21,"column":34}},"3":{"start":{"line":68,"column":22},"end":{"line":68,"column":40}},"4":{"start":{"line":30,"column":22},"end":{"line":30,"column":36}},"5":{"start":{"line":1,"column":35},"end":{"line":1,"column":null}},"6":{"start":{"line":25,"column":2},"end":{"line":27,"column":null}},"7":{"start":{"line":35,"column":19},"end":{"line":35,"column":null}},"8":{"start":{"line":36,"column":2},"end":{"line":36,"column":null}},"9":{"start":{"line":38,"column":2},"end":{"line":42,"column":null}},"10":{"start":{"line":49,"column":2},"end":{"line":51,"column":null}},"11":{"start":{"line":58,"column":2},"end":{"line":61,"column":null}},"12":{"start":{"line":74,"column":2},"end":{"line":88,"column":null}},"13":{"start":{"line":74,"column":15},"end":{"line":74,"column":18}},"14":{"start":{"line":75,"column":4},"end":{"line":86,"column":null}},"15":{"start":{"line":76,"column":21},"end":{"line":76,"column":null}},"16":{"start":{"line":77,"column":6},"end":{"line":79,"column":null}},"17":{"start":{"line":78,"column":8},"end":{"line":78,"column":null}},"18":{"start":{"line":81,"column":6},"end":{"line":85,"column":null}},"19":{"start":{"line":84,"column":8},"end":{"line":84,"column":null}},"20":{"start":{"line":87,"column":4},"end":{"line":87,"column":null}},"21":{"start":{"line":87,"column":35},"end":{"line":87,"column":null}},"22":{"start":{"line":89,"column":2},"end":{"line":89,"column":null}}},"fnMap":{"0":{"name":"getDocuments","decl":{"start":{"line":21,"column":22},"end":{"line":21,"column":34}},"loc":{"start":{"line":23,"column":22},"end":{"line":28,"column":null}}},"1":{"name":"uploadDocument","decl":{"start":{"line":30,"column":22},"end":{"line":30,"column":36}},"loc":{"start":{"line":33,"column":22},"end":{"line":43,"column":null}}},"2":{"name":"getDocumentStatus","decl":{"start":{"line":45,"column":22},"end":{"line":45,"column":39}},"loc":{"start":{"line":47,"column":22},"end":{"line":52,"column":null}}},"3":{"name":"deleteDocument","decl":{"start":{"line":54,"column":22},"end":{"line":54,"column":36}},"loc":{"start":{"line":56,"column":22},"end":{"line":62,"column":null}}},"4":{"name":"pollDocumentStatus","decl":{"start":{"line":68,"column":22},"end":{"line":68,"column":40}},"loc":{"start":{"line":72,"column":18},"end":{"line":90,"column":null}}},"5":{"name":"(anonymous_11)","decl":{"start":{"line":87,"column":22},"end":{"line":87,"column":23}},"loc":{"start":{"line":87,"column":35},"end":{"line":87,"column":null}}}},"branchMap":{"0":{"loc":{"start":{"line":71,"column":2},"end":{"line":71,"column":19}},"type":"default-arg","locations":[{"start":{"line":71,"column":15},"end":{"line":71,"column":19}}]},"1":{"loc":{"start":{"line":72,"column":2},"end":{"line":72,"column":18}},"type":"default-arg","locations":[{"start":{"line":72,"column":16},"end":{"line":72,"column":18}}]},"2":{"loc":{"start":{"line":77,"column":6},"end":{"line":79,"column":null}},"type":"if","locations":[{"start":{"line":77,"column":6},"end":{"line":79,"column":null}}]},"3":{"loc":{"start":{"line":77,"column":10},"end":{"line":77,"column":66}},"type":"binary-expr","locations":[{"start":{"line":77,"column":10},"end":{"line":77,"column":39}},{"start":{"line":77,"column":39},"end":{"line":77,"column":66}}]},"4":{"loc":{"start":{"line":81,"column":6},"end":{"line":85,"column":null}},"type":"if","locations":[{"start":{"line":81,"column":6},"end":{"line":85,"column":null}},{"start":{"line":83,"column":13},"end":{"line":85,"column":null}}]},"5":{"loc":{"start":{"line":81,"column":10},"end":{"line":81,"column":56}},"type":"binary-expr","locations":[{"start":{"line":81,"column":10},"end":{"line":81,"column":33}},{"start":{"line":81,"column":37},"end":{"line":81,"column":56}}]}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0},"b":{"0":[0],"1":[0],"2":[0],"3":[0,0],"4":[0,0],"5":[0,0]}} -} diff --git a/apps/web/coverage/lcov-report/base.css b/apps/web/coverage/lcov-report/base.css deleted file mode 100644 index f418035..0000000 --- a/apps/web/coverage/lcov-report/base.css +++ /dev/null @@ -1,224 +0,0 @@ -body, html { - margin:0; padding: 0; - height: 100%; -} -body { - font-family: Helvetica Neue, Helvetica, Arial; - font-size: 14px; - color:#333; -} -.small { font-size: 12px; } -*, *:after, *:before { - -webkit-box-sizing:border-box; - -moz-box-sizing:border-box; - box-sizing:border-box; - } -h1 { font-size: 20px; margin: 0;} -h2 { font-size: 14px; } -pre { - font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; - margin: 0; - padding: 0; - -moz-tab-size: 2; - -o-tab-size: 2; - tab-size: 2; -} -a { color:#0074D9; text-decoration:none; } -a:hover { text-decoration:underline; } -.strong { font-weight: bold; } -.space-top1 { padding: 10px 0 0 0; } -.pad2y { padding: 20px 0; } -.pad1y { padding: 10px 0; } -.pad2x { padding: 0 20px; } -.pad2 { padding: 20px; } -.pad1 { padding: 10px; } -.space-left2 { padding-left:55px; } -.space-right2 { padding-right:20px; } -.center { text-align:center; } -.clearfix { display:block; } -.clearfix:after { - content:''; - display:block; - height:0; - clear:both; - visibility:hidden; - } -.fl { float: left; } -@media only screen and (max-width:640px) { - .col3 { width:100%; max-width:100%; } - .hide-mobile { display:none!important; } -} - -.quiet { - color: #7f7f7f; - color: rgba(0,0,0,0.5); -} -.quiet a { opacity: 0.7; } - -.fraction { - font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; - font-size: 10px; - color: #555; - background: #E8E8E8; - padding: 4px 5px; - border-radius: 3px; - vertical-align: middle; -} - -div.path a:link, div.path a:visited { color: #333; } -table.coverage { - border-collapse: collapse; - margin: 10px 0 0 0; - padding: 0; -} - -table.coverage td { - margin: 0; - padding: 0; - vertical-align: top; -} -table.coverage td.line-count { - text-align: right; - padding: 0 5px 0 20px; -} -table.coverage td.line-coverage { - text-align: right; - padding-right: 10px; - min-width:20px; -} - -table.coverage td span.cline-any { - display: inline-block; - padding: 0 5px; - width: 100%; -} -.missing-if-branch { - display: inline-block; - margin-right: 5px; - border-radius: 3px; - position: relative; - padding: 0 4px; - background: #333; - color: yellow; -} - -.skip-if-branch { - display: none; - margin-right: 10px; - position: relative; - padding: 0 4px; - background: #ccc; - color: white; -} -.missing-if-branch .typ, .skip-if-branch .typ { - color: inherit !important; -} -.coverage-summary { - border-collapse: collapse; - width: 100%; -} -.coverage-summary tr { border-bottom: 1px solid #bbb; } -.keyline-all { border: 1px solid #ddd; } -.coverage-summary td, .coverage-summary th { padding: 10px; } -.coverage-summary tbody { border: 1px solid #bbb; } -.coverage-summary td { border-right: 1px solid #bbb; } -.coverage-summary td:last-child { border-right: none; } -.coverage-summary th { - text-align: left; - font-weight: normal; - white-space: nowrap; -} -.coverage-summary th.file { border-right: none !important; } -.coverage-summary th.pct { } -.coverage-summary th.pic, -.coverage-summary th.abs, -.coverage-summary td.pct, -.coverage-summary td.abs { text-align: right; } -.coverage-summary td.file { white-space: nowrap; } -.coverage-summary td.pic { min-width: 120px !important; } -.coverage-summary tfoot td { } - -.coverage-summary .sorter { - height: 10px; - width: 7px; - display: inline-block; - margin-left: 0.5em; - background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; -} -.coverage-summary .sorted .sorter { - background-position: 0 -20px; -} -.coverage-summary .sorted-desc .sorter { - background-position: 0 -10px; -} -.status-line { height: 10px; } -/* yellow */ -.cbranch-no { background: yellow !important; color: #111; } -/* dark red */ -.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } -.low .chart { border:1px solid #C21F39 } -.highlighted, -.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ - background: #C21F39 !important; -} -/* medium red */ -.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } -/* light red */ -.low, .cline-no { background:#FCE1E5 } -/* light green */ -.high, .cline-yes { background:rgb(230,245,208) } -/* medium green */ -.cstat-yes { background:rgb(161,215,106) } -/* dark green */ -.status-line.high, .high .cover-fill { background:rgb(77,146,33) } -.high .chart { border:1px solid rgb(77,146,33) } -/* dark yellow (gold) */ -.status-line.medium, .medium .cover-fill { background: #f9cd0b; } -.medium .chart { border:1px solid #f9cd0b; } -/* light yellow */ -.medium { background: #fff4c2; } - -.cstat-skip { background: #ddd; color: #111; } -.fstat-skip { background: #ddd; color: #111 !important; } -.cbranch-skip { background: #ddd !important; color: #111; } - -span.cline-neutral { background: #eaeaea; } - -.coverage-summary td.empty { - opacity: .5; - padding-top: 4px; - padding-bottom: 4px; - line-height: 1; - color: #888; -} - -.cover-fill, .cover-empty { - display:inline-block; - height: 12px; -} -.chart { - line-height: 0; -} -.cover-empty { - background: white; -} -.cover-full { - border-right: none !important; -} -pre.prettyprint { - border: none !important; - padding: 0 !important; - margin: 0 !important; -} -.com { color: #999 !important; } -.ignore-none { color: #999; font-weight: normal; } - -.wrapper { - min-height: 100%; - height: auto !important; - height: 100%; - margin: 0 auto -48px; -} -.footer, .push { - height: 48px; -} diff --git a/apps/web/coverage/lcov-report/block-navigation.js b/apps/web/coverage/lcov-report/block-navigation.js deleted file mode 100644 index 530d1ed..0000000 --- a/apps/web/coverage/lcov-report/block-navigation.js +++ /dev/null @@ -1,87 +0,0 @@ -/* eslint-disable */ -var jumpToCode = (function init() { - // Classes of code we would like to highlight in the file view - var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; - - // Elements to highlight in the file listing view - var fileListingElements = ['td.pct.low']; - - // We don't want to select elements that are direct descendants of another match - var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` - - // Selector that finds elements on the page to which we can jump - var selector = - fileListingElements.join(', ') + - ', ' + - notSelector + - missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` - - // The NodeList of matching elements - var missingCoverageElements = document.querySelectorAll(selector); - - var currentIndex; - - function toggleClass(index) { - missingCoverageElements - .item(currentIndex) - .classList.remove('highlighted'); - missingCoverageElements.item(index).classList.add('highlighted'); - } - - function makeCurrent(index) { - toggleClass(index); - currentIndex = index; - missingCoverageElements.item(index).scrollIntoView({ - behavior: 'smooth', - block: 'center', - inline: 'center' - }); - } - - function goToPrevious() { - var nextIndex = 0; - if (typeof currentIndex !== 'number' || currentIndex === 0) { - nextIndex = missingCoverageElements.length - 1; - } else if (missingCoverageElements.length > 1) { - nextIndex = currentIndex - 1; - } - - makeCurrent(nextIndex); - } - - function goToNext() { - var nextIndex = 0; - - if ( - typeof currentIndex === 'number' && - currentIndex < missingCoverageElements.length - 1 - ) { - nextIndex = currentIndex + 1; - } - - makeCurrent(nextIndex); - } - - return function jump(event) { - if ( - document.getElementById('fileSearch') === document.activeElement && - document.activeElement != null - ) { - // if we're currently focused on the search input, we don't want to navigate - return; - } - - switch (event.which) { - case 78: // n - case 74: // j - goToNext(); - break; - case 66: // b - case 75: // k - case 80: // p - goToPrevious(); - break; - } - }; -})(); -window.addEventListener('keydown', jumpToCode); diff --git a/apps/web/coverage/lcov-report/favicon.png b/apps/web/coverage/lcov-report/favicon.png deleted file mode 100644 index c1525b8..0000000 Binary files a/apps/web/coverage/lcov-report/favicon.png and /dev/null differ diff --git a/apps/web/coverage/lcov-report/index.html b/apps/web/coverage/lcov-report/index.html deleted file mode 100644 index 31ce679..0000000 --- a/apps/web/coverage/lcov-report/index.html +++ /dev/null @@ -1,401 +0,0 @@ - - - - - - Code coverage report for All files - - - - - - - - - -
-
-

All files

-
- -
- 15.73% - Statements - 101/642 -
- - -
- 27.47% - Branches - 86/313 -
- - -
- 8.82% - Functions - 12/136 -
- - -
- 16.88% - Lines - 101/598 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
src -
-
0%0/3100%0/0100%0/00%0/1
src/app -
-
0%0/180%0/60%0/30%0/17
src/app/(auth) -
-
0%0/1100%0/00%0/10%0/1
src/app/(auth)/login -
-
97.56%40/41100%30/30100%5/597.56%40/41
src/app/(auth)/signup -
-
93.84%61/6584.84%56/66100%7/793.84%61/65
src/app/api/auth/[...nextauth] -
-
0%0/5100%0/0100%0/00%0/4
src/app/courses -
-
0%0/280%0/100%0/60%0/27
src/app/courses/[courseId] -
-
0%0/440%0/150%0/120%0/42
src/app/courses/[courseId]/documents/[documentId]/preview -
-
0%0/290%0/200%0/70%0/29
src/app/courses/[courseId]/study -
-
0%0/220%0/20%0/30%0/21
src/app/dashboard -
-
0%0/240%0/110%0/40%0/23
src/components/courses -
-
0%0/640%0/390%0/180%0/57
src/components/documents -
-
0%0/940%0/270%0/240%0/81
src/components/providers -
-
0%0/4100%0/00%0/10%0/3
src/components/study -
-
0%0/260%0/70%0/60%0/25
src/lib -
-
0%0/200%0/170%0/40%0/19
src/lib/api -
-
0%0/760%0/200%0/190%0/69
src/lib/auth -
-
0%0/290%0/250%0/40%0/27
src/lib/middleware -
-
0%0/170%0/70%0/20%0/16
src/lib/services -
-
0%0/320%0/110%0/100%0/30
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/prettify.css b/apps/web/coverage/lcov-report/prettify.css deleted file mode 100644 index b317a7c..0000000 --- a/apps/web/coverage/lcov-report/prettify.css +++ /dev/null @@ -1 +0,0 @@ -.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/apps/web/coverage/lcov-report/prettify.js b/apps/web/coverage/lcov-report/prettify.js deleted file mode 100644 index b322523..0000000 --- a/apps/web/coverage/lcov-report/prettify.js +++ /dev/null @@ -1,2 +0,0 @@ -/* eslint-disable */ -window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/apps/web/coverage/lcov-report/sort-arrow-sprite.png b/apps/web/coverage/lcov-report/sort-arrow-sprite.png deleted file mode 100644 index 6ed6831..0000000 Binary files a/apps/web/coverage/lcov-report/sort-arrow-sprite.png and /dev/null differ diff --git a/apps/web/coverage/lcov-report/sorter.js b/apps/web/coverage/lcov-report/sorter.js deleted file mode 100644 index 4ed70ae..0000000 --- a/apps/web/coverage/lcov-report/sorter.js +++ /dev/null @@ -1,210 +0,0 @@ -/* eslint-disable */ -var addSorting = (function() { - 'use strict'; - var cols, - currentSort = { - index: 0, - desc: false - }; - - // returns the summary table element - function getTable() { - return document.querySelector('.coverage-summary'); - } - // returns the thead element of the summary table - function getTableHeader() { - return getTable().querySelector('thead tr'); - } - // returns the tbody element of the summary table - function getTableBody() { - return getTable().querySelector('tbody'); - } - // returns the th element for nth column - function getNthColumn(n) { - return getTableHeader().querySelectorAll('th')[n]; - } - - function onFilterInput() { - const searchValue = document.getElementById('fileSearch').value; - const rows = document.getElementsByTagName('tbody')[0].children; - - // Try to create a RegExp from the searchValue. If it fails (invalid regex), - // it will be treated as a plain text search - let searchRegex; - try { - searchRegex = new RegExp(searchValue, 'i'); // 'i' for case-insensitive - } catch (error) { - searchRegex = null; - } - - for (let i = 0; i < rows.length; i++) { - const row = rows[i]; - let isMatch = false; - - if (searchRegex) { - // If a valid regex was created, use it for matching - isMatch = searchRegex.test(row.textContent); - } else { - // Otherwise, fall back to the original plain text search - isMatch = row.textContent - .toLowerCase() - .includes(searchValue.toLowerCase()); - } - - row.style.display = isMatch ? '' : 'none'; - } - } - - // loads the search box - function addSearchBox() { - var template = document.getElementById('filterTemplate'); - var templateClone = template.content.cloneNode(true); - templateClone.getElementById('fileSearch').oninput = onFilterInput; - template.parentElement.appendChild(templateClone); - } - - // loads all columns - function loadColumns() { - var colNodes = getTableHeader().querySelectorAll('th'), - colNode, - cols = [], - col, - i; - - for (i = 0; i < colNodes.length; i += 1) { - colNode = colNodes[i]; - col = { - key: colNode.getAttribute('data-col'), - sortable: !colNode.getAttribute('data-nosort'), - type: colNode.getAttribute('data-type') || 'string' - }; - cols.push(col); - if (col.sortable) { - col.defaultDescSort = col.type === 'number'; - colNode.innerHTML = - colNode.innerHTML + ''; - } - } - return cols; - } - // attaches a data attribute to every tr element with an object - // of data values keyed by column name - function loadRowData(tableRow) { - var tableCols = tableRow.querySelectorAll('td'), - colNode, - col, - data = {}, - i, - val; - for (i = 0; i < tableCols.length; i += 1) { - colNode = tableCols[i]; - col = cols[i]; - val = colNode.getAttribute('data-value'); - if (col.type === 'number') { - val = Number(val); - } - data[col.key] = val; - } - return data; - } - // loads all row data - function loadData() { - var rows = getTableBody().querySelectorAll('tr'), - i; - - for (i = 0; i < rows.length; i += 1) { - rows[i].data = loadRowData(rows[i]); - } - } - // sorts the table using the data for the ith column - function sortByIndex(index, desc) { - var key = cols[index].key, - sorter = function(a, b) { - a = a.data[key]; - b = b.data[key]; - return a < b ? -1 : a > b ? 1 : 0; - }, - finalSorter = sorter, - tableBody = document.querySelector('.coverage-summary tbody'), - rowNodes = tableBody.querySelectorAll('tr'), - rows = [], - i; - - if (desc) { - finalSorter = function(a, b) { - return -1 * sorter(a, b); - }; - } - - for (i = 0; i < rowNodes.length; i += 1) { - rows.push(rowNodes[i]); - tableBody.removeChild(rowNodes[i]); - } - - rows.sort(finalSorter); - - for (i = 0; i < rows.length; i += 1) { - tableBody.appendChild(rows[i]); - } - } - // removes sort indicators for current column being sorted - function removeSortIndicators() { - var col = getNthColumn(currentSort.index), - cls = col.className; - - cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); - col.className = cls; - } - // adds sort indicators for current column being sorted - function addSortIndicators() { - getNthColumn(currentSort.index).className += currentSort.desc - ? ' sorted-desc' - : ' sorted'; - } - // adds event listeners for all sorter widgets - function enableUI() { - var i, - el, - ithSorter = function ithSorter(i) { - var col = cols[i]; - - return function() { - var desc = col.defaultDescSort; - - if (currentSort.index === i) { - desc = !currentSort.desc; - } - sortByIndex(i, desc); - removeSortIndicators(); - currentSort.index = i; - currentSort.desc = desc; - addSortIndicators(); - }; - }; - for (i = 0; i < cols.length; i += 1) { - if (cols[i].sortable) { - // add the click event handler on the th so users - // dont have to click on those tiny arrows - el = getNthColumn(i).querySelector('.sorter').parentElement; - if (el.addEventListener) { - el.addEventListener('click', ithSorter(i)); - } else { - el.attachEvent('onclick', ithSorter(i)); - } - } - } - } - // adds sorting functionality to the UI - return function() { - if (!getTable()) { - return; - } - cols = loadColumns(); - loadData(); - addSearchBox(); - addSortIndicators(); - enableUI(); - }; -})(); - -window.addEventListener('load', addSorting); diff --git a/apps/web/coverage/lcov-report/src/app/(auth)/index.html b/apps/web/coverage/lcov-report/src/app/(auth)/index.html deleted file mode 100644 index 80dac0b..0000000 --- a/apps/web/coverage/lcov-report/src/app/(auth)/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for src/app/(auth) - - - - - - - - - -
-
-

All files src/app/(auth)

-
- -
- 0% - Statements - 0/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
layout.tsx -
-
0%0/1100%0/00%0/10%0/1
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/(auth)/layout.tsx.html b/apps/web/coverage/lcov-report/src/app/(auth)/layout.tsx.html deleted file mode 100644 index 547a4f7..0000000 --- a/apps/web/coverage/lcov-report/src/app/(auth)/layout.tsx.html +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - Code coverage report for src/app/(auth)/layout.tsx - - - - - - - - - -
-
-

All files / src/app/(auth) layout.tsx

-
- -
- 0% - Statements - 0/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
/**
- * Authentication layout
- * Shared layout for login and signup pages
- */
-import { ReactNode } from 'react';
- 
-interface AuthLayoutProps {
-  children: ReactNode;
-}
- 
-export default function AuthLayout({ children }: AuthLayoutProps) {
-  return (
-    <div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
-      <div className="max-w-md w-full space-y-8">
-        <div className="text-center">
-          <h1 className="text-3xl font-bold text-gray-900">BitPolito Academy</h1>
-          <p className="mt-2 text-sm text-gray-600">Learn Bitcoin with interactive courses</p>
-        </div>
-        {children}
-      </div>
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/(auth)/login/index.html b/apps/web/coverage/lcov-report/src/app/(auth)/login/index.html deleted file mode 100644 index 47ce279..0000000 --- a/apps/web/coverage/lcov-report/src/app/(auth)/login/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for src/app/(auth)/login - - - - - - - - - -
-
-

All files src/app/(auth)/login

-
- -
- 97.56% - Statements - 40/41 -
- - -
- 100% - Branches - 30/30 -
- - -
- 100% - Functions - 5/5 -
- - -
- 97.56% - Lines - 40/41 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
page.tsx -
-
97.56%40/41100%30/30100%5/597.56%40/41
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/(auth)/login/page.tsx.html b/apps/web/coverage/lcov-report/src/app/(auth)/login/page.tsx.html deleted file mode 100644 index 60f7e7b..0000000 --- a/apps/web/coverage/lcov-report/src/app/(auth)/login/page.tsx.html +++ /dev/null @@ -1,772 +0,0 @@ - - - - - - Code coverage report for src/app/(auth)/login/page.tsx - - - - - - - - - -
-
-

All files / src/app/(auth)/login page.tsx

-
- -
- 97.56% - Statements - 40/41 -
- - -
- 100% - Branches - 30/30 -
- - -
- 100% - Functions - 5/5 -
- - -
- 97.56% - Lines - 40/41 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230  -  -  -  -  -  -2x -2x -2x -2x -  -  -  -  -  -  -  -2x -327x -327x -327x -327x -  -327x -325x -325x -325x -  -  -  -325x -  -  -  -  -325x -15x -  -  -15x -3x -12x -2x -  -  -  -15x -6x -  -  -15x -15x -  -  -  -  -  -325x -15x -  -  -15x -  -  -15x -6x -  -  -9x -  -9x -9x -  -  -  -  -  -  -8x -2x -6x -6x -6x -  -  -  -  -8x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -179x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -106x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-/**
- * Login page component
- * Handles user authentication with form validation
- */
-import { signIn } from 'next-auth/react';
-import Link from 'next/link';
-import { useRouter, useSearchParams } from 'next/navigation';
-import { FormEvent, useState } from 'react';
- 
-interface FormErrors {
-  email?: string;
-  password?: string;
-  general?: string;
-}
- 
-export default function LoginPage() {
-  const router = useRouter();
-  const searchParams = useSearchParams();
-  const callbackUrl = searchParams.get('callbackUrl') || '/dashboard';
-  const errorParam = searchParams.get('error');
- 
-  const [email, setEmail] = useState('');
-  const [password, setPassword] = useState('');
-  const [isLoading, setIsLoading] = useState(false);
-  const [errors, setErrors] = useState<FormErrors>({});
- 
-  // Handle session expired error from URL
-  const sessionError =
-    errorParam === 'SessionExpired' ? 'Your session has expired. Please log in again.' : null;
- 
-  /**
-   * Validate form fields
-   */
-  const validateForm = (): boolean => {
-    const newErrors: FormErrors = {};
- 
-    // Email validation
-    if (!email) {
-      newErrors.email = 'Email is required';
-    } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
-      newErrors.email = 'Please enter a valid email address';
-    }
- 
-    // Password validation
-    if (!password) {
-      newErrors.password = 'Password is required';
-    }
- 
-    setErrors(newErrors);
-    return Object.keys(newErrors).length === 0;
-  };
- 
-  /**
-   * Handle form submission
-   */
-  const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
-    e.preventDefault();
- 
-    // Clear previous errors
-    setErrors({});
- 
-    // Validate form
-    if (!validateForm()) {
-      return;
-    }
- 
-    setIsLoading(true);
- 
-    try {
-      const result = await signIn('credentials', {
-        email,
-        password,
-        redirect: false,
-        callbackUrl,
-      });
- 
-      if (result?.error) {
-        setErrors({ general: result.error });
-      } else if (result?.ok) {
-        router.push(callbackUrl);
-        router.refresh();
-      }
-    } catch (error) {
-      setErrors({ general: 'An unexpected error occurred. Please try again.' });
-    } finally {
-      setIsLoading(false);
-    }
-  };
- 
-  return (
-    <div className="mt-8 bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
-      <h2 className="text-center text-2xl font-bold text-gray-900 mb-6">Sign in to your account</h2>
- 
-      {/* Session expired error */}
-      {sessionError && (
-        <div className="mb-4 p-3 rounded bg-yellow-50 border border-yellow-200">
-          <p className="text-sm text-yellow-800">{sessionError}</p>
-        </div>
-      )}
- 
-      {/* General error message */}
-      {errors.general && (
-        <div className="mb-4 p-3 rounded bg-red-50 border border-red-200">
-          <p className="text-sm text-red-600">{errors.general}</p>
-        </div>
-      )}
- 
-      <form className="space-y-6" onSubmit={handleSubmit} noValidate>
-        {/* Email field */}
-        <div>
-          <label htmlFor="email" className="block text-sm font-medium text-gray-700">
-            Email address
-          </label>
-          <div className="mt-1">
-            <input
-              id="email"
-              name="email"
-              type="email"
-              autoComplete="email"
-              required
-              value={email}
-              onChange={(e) => setEmail(e.target.value)}
-              className={`appearance-none block w-full px-3 py-2 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-orange-500 focus:border-orange-500 sm:text-sm ${
-                errors.email ? 'border-red-300' : 'border-gray-300'
-              }`}
-              placeholder="you@example.com"
-              aria-invalid={errors.email ? 'true' : 'false'}
-              aria-describedby={errors.email ? 'email-error' : undefined}
-            />
-          </div>
-          {errors.email && (
-            <p className="mt-1 text-sm text-red-600" id="email-error" role="alert">
-              {errors.email}
-            </p>
-          )}
-        </div>
- 
-        {/* Password field */}
-        <div>
-          <label htmlFor="password" className="block text-sm font-medium text-gray-700">
-            Password
-          </label>
-          <div className="mt-1">
-            <input
-              id="password"
-              name="password"
-              type="password"
-              autoComplete="current-password"
-              required
-              value={password}
-              onChange={(e) => setPassword(e.target.value)}
-              className={`appearance-none block w-full px-3 py-2 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-orange-500 focus:border-orange-500 sm:text-sm ${
-                errors.password ? 'border-red-300' : 'border-gray-300'
-              }`}
-              placeholder="••••••••"
-              aria-invalid={errors.password ? 'true' : 'false'}
-              aria-describedby={errors.password ? 'password-error' : undefined}
-            />
-          </div>
-          {errors.password && (
-            <p className="mt-1 text-sm text-red-600" id="password-error" role="alert">
-              {errors.password}
-            </p>
-          )}
-        </div>
- 
-        {/* Submit button */}
-        <div>
-          <button
-            type="submit"
-            disabled={isLoading}
-            className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-orange-600 hover:bg-orange-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-orange-500 disabled:opacity-50 disabled:cursor-not-allowed"
-          >
-            {isLoading ? (
-              <>
-                <svg
-                  className="animate-spin -ml-1 mr-3 h-5 w-5 text-white"
-                  xmlns="http://www.w3.org/2000/svg"
-                  fill="none"
-                  viewBox="0 0 24 24"
-                >
-                  <circle
-                    className="opacity-25"
-                    cx="12"
-                    cy="12"
-                    r="10"
-                    stroke="currentColor"
-                    strokeWidth="4"
-                  />
-                  <path
-                    className="opacity-75"
-                    fill="currentColor"
-                    d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
-                  />
-                </svg>
-                Signing in...
-              </>
-            ) : (
-              'Sign in'
-            )}
-          </button>
-        </div>
-      </form>
- 
-      {/* Sign up link */}
-      <div className="mt-6">
-        <div className="relative">
-          <div className="absolute inset-0 flex items-center">
-            <div className="w-full border-t border-gray-300" />
-          </div>
-          <div className="relative flex justify-center text-sm">
-            <span className="px-2 bg-white text-gray-500">Don&apos;t have an account?</span>
-          </div>
-        </div>
- 
-        <div className="mt-6">
-          <Link
-            href="/signup"
-            className="w-full flex justify-center py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-orange-500"
-          >
-            Create an account
-          </Link>
-        </div>
-      </div>
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/(auth)/signup/index.html b/apps/web/coverage/lcov-report/src/app/(auth)/signup/index.html deleted file mode 100644 index 3716101..0000000 --- a/apps/web/coverage/lcov-report/src/app/(auth)/signup/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for src/app/(auth)/signup - - - - - - - - - -
-
-

All files src/app/(auth)/signup

-
- -
- 93.84% - Statements - 61/65 -
- - -
- 84.84% - Branches - 56/66 -
- - -
- 100% - Functions - 7/7 -
- - -
- 93.84% - Lines - 61/65 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
page.tsx -
-
93.84%61/6584.84%56/66100%7/793.84%61/65
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/(auth)/signup/page.tsx.html b/apps/web/coverage/lcov-report/src/app/(auth)/signup/page.tsx.html deleted file mode 100644 index ac236bd..0000000 --- a/apps/web/coverage/lcov-report/src/app/(auth)/signup/page.tsx.html +++ /dev/null @@ -1,1078 +0,0 @@ - - - - - - Code coverage report for src/app/(auth)/signup/page.tsx - - - - - - - - - -
-
-

All files / src/app/(auth)/signup page.tsx

-
- -
- 93.84% - Statements - 61/65 -
- - -
- 84.84% - Branches - 56/66 -
- - -
- 100% - Functions - 7/7 -
- - -
- 93.84% - Lines - 61/65 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242 -243 -244 -245 -246 -247 -248 -249 -250 -251 -252 -253 -254 -255 -256 -257 -258 -259 -260 -261 -262 -263 -264 -265 -266 -267 -268 -269 -270 -271 -272 -273 -274 -275 -276 -277 -278 -279 -280 -281 -282 -283 -284 -285 -286 -287 -288 -289 -290 -291 -292 -293 -294 -295 -296 -297 -298 -299 -300 -301 -302 -303 -304 -305 -306 -307 -308 -309 -310 -311 -312 -313 -314 -315 -316 -317 -318 -319 -320 -321 -322 -323 -324 -325 -326 -327 -328 -329 -330 -331 -332  -  -  -  -  -  -2x -2x -2x -2x -  -  -2x -  -  -  -  -  -  -  -  -  -2x -774x -  -774x -772x -772x -772x -772x -772x -  -  -  -  -772x -18x -  -  -18x -1x -17x -1x -  -  -  -18x -  -18x -1x -17x -1x -16x -1x -15x -1x -  -  -  -18x -1x -17x -1x -  -  -  -18x -  -  -  -18x -18x -  -  -  -  -  -772x -18x -  -  -18x -  -  -18x -8x -  -  -10x -  -10x -  -10x -  -  -  -  -  -  -  -  -  -  -  -8x -3x -  -3x -2x -1x -  -  -1x -  -3x -  -  -  -5x -  -  -  -  -  -  -5x -  -  -5x -5x -5x -  -  -1x -  -9x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -17x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -281x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -217x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -209x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-/**
- * Signup page component
- * Handles user registration with form validation
- */
-import Link from 'next/link';
-import { useRouter } from 'next/navigation';
-import { signIn } from 'next-auth/react';
-import { FormEvent, useState } from 'react';
- 
-// Backend API URL
-const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000';
- 
-interface FormErrors {
-  email?: string;
-  password?: string;
-  confirmPassword?: string;
-  displayName?: string;
-  general?: string;
-}
- 
-export default function SignupPage() {
-  const router = useRouter();
- 
-  const [email, setEmail] = useState('');
-  const [password, setPassword] = useState('');
-  const [confirmPassword, setConfirmPassword] = useState('');
-  const [displayName, setDisplayName] = useState('');
-  const [isLoading, setIsLoading] = useState(false);
-  const [errors, setErrors] = useState<FormErrors>({});
- 
-  /**
-   * Validate form fields
-   */
-  const validateForm = (): boolean => {
-    const newErrors: FormErrors = {};
- 
-    // Email validation
-    if (!email) {
-      newErrors.email = 'Email is required';
-    } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
-      newErrors.email = 'Please enter a valid email address';
-    }
- 
-    // Password validation
-    Iif (!password) {
-      newErrors.password = 'Password is required';
-    } else if (password.length < 8) {
-      newErrors.password = 'Password must be at least 8 characters long';
-    } else if (!/[A-Z]/.test(password)) {
-      newErrors.password = 'Password must contain at least one uppercase letter';
-    } else if (!/[a-z]/.test(password)) {
-      newErrors.password = 'Password must contain at least one lowercase letter';
-    } else if (!/\d/.test(password)) {
-      newErrors.password = 'Password must contain at least one digit';
-    }
- 
-    // Confirm password validation
-    if (!confirmPassword) {
-      newErrors.confirmPassword = 'Please confirm your password';
-    } else if (password !== confirmPassword) {
-      newErrors.confirmPassword = 'Passwords do not match';
-    }
- 
-    // Display name validation (optional but if provided, must be valid)
-    Iif (displayName && displayName.length < 2) {
-      newErrors.displayName = 'Display name must be at least 2 characters long';
-    }
- 
-    setErrors(newErrors);
-    return Object.keys(newErrors).length === 0;
-  };
- 
-  /**
-   * Handle form submission
-   */
-  const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
-    e.preventDefault();
- 
-    // Clear previous errors
-    setErrors({});
- 
-    // Validate form
-    if (!validateForm()) {
-      return;
-    }
- 
-    setIsLoading(true);
- 
-    try {
-      // Register the user
-      const registerResponse = await fetch(`${API_URL}/api/auth/register`, {
-        method: 'POST',
-        headers: {
-          'Content-Type': 'application/json',
-        },
-        body: JSON.stringify({
-          email,
-          password,
-          display_name: displayName || null,
-        }),
-      });
- 
-      if (!registerResponse.ok) {
-        const error = await registerResponse.json();
- 
-        if (registerResponse.status === 409) {
-          setErrors({ email: 'A user with this email already exists' });
-        } else Iif (registerResponse.status === 400) {
-          setErrors({ general: error.detail || 'Invalid input data' });
-        } else {
-          setErrors({ general: error.detail || 'Registration failed' });
-        }
-        return;
-      }
- 
-      // Auto-login after successful registration
-      const result = await signIn('credentials', {
-        email,
-        password,
-        redirect: false,
-        callbackUrl: '/dashboard',
-      });
- 
-      Iif (result?.error) {
-        // Registration succeeded but login failed - redirect to login page
-        router.push('/login?message=Registration successful. Please log in.');
-      } else if (result?.ok) {
-        router.push('/dashboard');
-        router.refresh();
-      }
-    } catch (error) {
-      setErrors({ general: 'An unexpected error occurred. Please try again.' });
-    } finally {
-      setIsLoading(false);
-    }
-  };
- 
-  return (
-    <div className="mt-8 bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
-      <h2 className="text-center text-2xl font-bold text-gray-900 mb-6">Create your account</h2>
- 
-      {/* General error message */}
-      {errors.general && (
-        <div className="mb-4 p-3 rounded bg-red-50 border border-red-200" role="alert">
-          <p className="text-sm text-red-600">{errors.general}</p>
-        </div>
-      )}
- 
-      <form className="space-y-6" onSubmit={handleSubmit} noValidate>
-        {/* Display name field (optional) */}
-        <div>
-          <label htmlFor="displayName" className="block text-sm font-medium text-gray-700">
-            Display name <span className="text-gray-400">(optional)</span>
-          </label>
-          <div className="mt-1">
-            <input
-              id="displayName"
-              name="displayName"
-              type="text"
-              autoComplete="name"
-              value={displayName}
-              onChange={(e) => setDisplayName(e.target.value)}
-              className={`appearance-none block w-full px-3 py-2 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-orange-500 focus:border-orange-500 sm:text-sm ${
-                errors.displayName ? 'border-red-300' : 'border-gray-300'
-              }`}
-              placeholder="Satoshi Nakamoto"
-              aria-invalid={errors.displayName ? 'true' : 'false'}
-              aria-describedby={errors.displayName ? 'displayName-error' : undefined}
-            />
-          </div>
-          {errors.displayName && (
-            <p className="mt-1 text-sm text-red-600" id="displayName-error" role="alert">
-              {errors.displayName}
-            </p>
-          )}
-        </div>
- 
-        {/* Email field */}
-        <div>
-          <label htmlFor="email" className="block text-sm font-medium text-gray-700">
-            Email address
-          </label>
-          <div className="mt-1">
-            <input
-              id="email"
-              name="email"
-              type="email"
-              autoComplete="email"
-              required
-              value={email}
-              onChange={(e) => setEmail(e.target.value)}
-              className={`appearance-none block w-full px-3 py-2 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-orange-500 focus:border-orange-500 sm:text-sm ${
-                errors.email ? 'border-red-300' : 'border-gray-300'
-              }`}
-              placeholder="you@example.com"
-              aria-invalid={errors.email ? 'true' : 'false'}
-              aria-describedby={errors.email ? 'email-error' : undefined}
-            />
-          </div>
-          {errors.email && (
-            <p className="mt-1 text-sm text-red-600" id="email-error" role="alert">
-              {errors.email}
-            </p>
-          )}
-        </div>
- 
-        {/* Password field */}
-        <div>
-          <label htmlFor="password" className="block text-sm font-medium text-gray-700">
-            Password
-          </label>
-          <div className="mt-1">
-            <input
-              id="password"
-              name="password"
-              type="password"
-              autoComplete="new-password"
-              required
-              value={password}
-              onChange={(e) => setPassword(e.target.value)}
-              className={`appearance-none block w-full px-3 py-2 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-orange-500 focus:border-orange-500 sm:text-sm ${
-                errors.password ? 'border-red-300' : 'border-gray-300'
-              }`}
-              placeholder="••••••••"
-              aria-invalid={errors.password ? 'true' : 'false'}
-              aria-describedby={errors.password ? 'password-error' : 'password-hint'}
-            />
-          </div>
-          {errors.password ? (
-            <p className="mt-1 text-sm text-red-600" id="password-error" role="alert">
-              {errors.password}
-            </p>
-          ) : (
-            <p className="mt-1 text-xs text-gray-500" id="password-hint">
-              Min 8 characters, with uppercase, lowercase, and a digit
-            </p>
-          )}
-        </div>
- 
-        {/* Confirm password field */}
-        <div>
-          <label htmlFor="confirmPassword" className="block text-sm font-medium text-gray-700">
-            Confirm password
-          </label>
-          <div className="mt-1">
-            <input
-              id="confirmPassword"
-              name="confirmPassword"
-              type="password"
-              autoComplete="new-password"
-              required
-              value={confirmPassword}
-              onChange={(e) => setConfirmPassword(e.target.value)}
-              className={`appearance-none block w-full px-3 py-2 border rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-orange-500 focus:border-orange-500 sm:text-sm ${
-                errors.confirmPassword ? 'border-red-300' : 'border-gray-300'
-              }`}
-              placeholder="••••••••"
-              aria-invalid={errors.confirmPassword ? 'true' : 'false'}
-              aria-describedby={errors.confirmPassword ? 'confirmPassword-error' : undefined}
-            />
-          </div>
-          {errors.confirmPassword && (
-            <p className="mt-1 text-sm text-red-600" id="confirmPassword-error" role="alert">
-              {errors.confirmPassword}
-            </p>
-          )}
-        </div>
- 
-        {/* Submit button */}
-        <div>
-          <button
-            type="submit"
-            disabled={isLoading}
-            className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-orange-600 hover:bg-orange-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-orange-500 disabled:opacity-50 disabled:cursor-not-allowed"
-          >
-            {isLoading ? (
-              <>
-                <svg
-                  className="animate-spin -ml-1 mr-3 h-5 w-5 text-white"
-                  xmlns="http://www.w3.org/2000/svg"
-                  fill="none"
-                  viewBox="0 0 24 24"
-                >
-                  <circle
-                    className="opacity-25"
-                    cx="12"
-                    cy="12"
-                    r="10"
-                    stroke="currentColor"
-                    strokeWidth="4"
-                  />
-                  <path
-                    className="opacity-75"
-                    fill="currentColor"
-                    d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
-                  />
-                </svg>
-                Creating account...
-              </>
-            ) : (
-              'Create account'
-            )}
-          </button>
-        </div>
-      </form>
- 
-      {/* Sign in link */}
-      <div className="mt-6">
-        <div className="relative">
-          <div className="absolute inset-0 flex items-center">
-            <div className="w-full border-t border-gray-300" />
-          </div>
-          <div className="relative flex justify-center text-sm">
-            <span className="px-2 bg-white text-gray-500">Already have an account?</span>
-          </div>
-        </div>
- 
-        <div className="mt-6">
-          <Link
-            href="/login"
-            className="w-full flex justify-center py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-orange-500"
-          >
-            Sign in instead
-          </Link>
-        </div>
-      </div>
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/api/auth/[...nextauth]/index.html b/apps/web/coverage/lcov-report/src/app/api/auth/[...nextauth]/index.html deleted file mode 100644 index 752d302..0000000 --- a/apps/web/coverage/lcov-report/src/app/api/auth/[...nextauth]/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for src/app/api/auth/[...nextauth] - - - - - - - - - -
-
-

All files src/app/api/auth/[...nextauth]

-
- -
- 0% - Statements - 0/5 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 0% - Lines - 0/4 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
route.ts -
-
0%0/5100%0/0100%0/00%0/4
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/api/auth/[...nextauth]/route.ts.html b/apps/web/coverage/lcov-report/src/app/api/auth/[...nextauth]/route.ts.html deleted file mode 100644 index 91d021c..0000000 --- a/apps/web/coverage/lcov-report/src/app/api/auth/[...nextauth]/route.ts.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - Code coverage report for src/app/api/auth/[...nextauth]/route.ts - - - - - - - - - -
-
-

All files / src/app/api/auth/[...nextauth] route.ts

-
- -
- 0% - Statements - 0/5 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 0% - Lines - 0/4 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10  -  -  -  -  -  -  -  -  - 
/**
- * NextAuth.js API route handler
- */
-import NextAuth from 'next-auth';
-import { authOptions } from '@/lib/auth/config';
- 
-const handler = NextAuth(authOptions);
- 
-export { handler as GET, handler as POST };
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/courses/[courseId]/documents/[documentId]/preview/index.html b/apps/web/coverage/lcov-report/src/app/courses/[courseId]/documents/[documentId]/preview/index.html deleted file mode 100644 index 833d4f2..0000000 --- a/apps/web/coverage/lcov-report/src/app/courses/[courseId]/documents/[documentId]/preview/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for src/app/courses/[courseId]/documents/[documentId]/preview - - - - - - - - - -
-
-

All files src/app/courses/[courseId]/documents/[documentId]/preview

-
- -
- 0% - Statements - 0/29 -
- - -
- 0% - Branches - 0/20 -
- - -
- 0% - Functions - 0/7 -
- - -
- 0% - Lines - 0/29 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
page.tsx -
-
0%0/290%0/200%0/70%0/29
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/courses/[courseId]/documents/[documentId]/preview/page.tsx.html b/apps/web/coverage/lcov-report/src/app/courses/[courseId]/documents/[documentId]/preview/page.tsx.html deleted file mode 100644 index 881ba7f..0000000 --- a/apps/web/coverage/lcov-report/src/app/courses/[courseId]/documents/[documentId]/preview/page.tsx.html +++ /dev/null @@ -1,562 +0,0 @@ - - - - - - Code coverage report for src/app/courses/[courseId]/documents/[documentId]/preview/page.tsx - - - - - - - - - -
-
-

All files / src/app/courses/[courseId]/documents/[documentId]/preview page.tsx

-
- -
- 0% - Statements - 0/29 -
- - -
- 0% - Branches - 0/20 -
- - -
- 0% - Functions - 0/7 -
- - -
- 0% - Lines - 0/29 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-import { useCallback, useEffect, useState } from 'react';
-import { useParams, useRouter } from 'next/navigation';
-import { useSession } from 'next-auth/react';
-import { getDocumentPreviewView } from '@/lib/api/documents';
-import type { DocumentPreviewView } from '@/lib/api/types';
- 
-export default function DocumentPreviewPage() {
-  const params = useParams();
-  const router = useRouter();
-  const courseId = params.courseId as string;
-  const documentId = params.documentId as string;
-  const { data: session } = useSession();
-  const accessToken = (session?.user as any)?.accessToken;
- 
-  const [preview, setPreview] = useState<DocumentPreviewView | null>(null);
-  const [loading, setLoading] = useState(true);
-  const [error, setError] = useState<string | null>(null);
- 
-  const load = useCallback(async () => {
-    try {
-      setError(null);
-      const data = await getDocumentPreviewView(documentId, accessToken);
-      setPreview(data);
-    } catch (err) {
-      setError(err instanceof Error ? err.message : 'Failed to load preview');
-    } finally {
-      setLoading(false);
-    }
-  }, [documentId, accessToken]);
- 
-  useEffect(() => {
-    load();
-  }, [load]);
- 
-  Iif (loading) {
-    return (
-      <main className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
-        <div className="animate-pulse space-y-6">
-          <div className="h-6 w-1/3 bg-gray-200 rounded" />
-          <div className="h-64 bg-gray-100 rounded-lg" />
-          <div className="h-40 bg-gray-100 rounded-lg" />
-        </div>
-      </main>
-    );
-  }
- 
-  Iif (error || !preview) {
-    return (
-      <main className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
-        <div className="rounded-lg border border-red-200 bg-red-50 p-6 text-center">
-          <p className="text-sm text-red-700">{error || 'Preview not available'}</p>
-          <div className="mt-3 flex items-center justify-center gap-3">
-            <button
-              onClick={load}
-              className="text-sm font-medium text-red-700 hover:text-red-800 underline"
-            >
-              Retry
-            </button>
-            <button
-              onClick={() => router.push(`/courses/${courseId}`)}
-              className="text-sm font-medium text-gray-600 hover:text-gray-800 underline"
-            >
-              Back to course
-            </button>
-          </div>
-        </div>
-      </main>
-    );
-  }
- 
-  return (
-    <main className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
-      {/* Header */}
-      <div className="mb-6 flex items-center gap-3">
-        <button
-          onClick={() => router.push(`/courses/${courseId}`)}
-          className="inline-flex items-center gap-1 text-sm text-gray-500 hover:text-gray-700"
-        >
-          <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor">
-            <path strokeLinecap="round" strokeLinejoin="round" d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18" />
-          </svg>
-          Back
-        </button>
-        <div className="flex-1 min-w-0">
-          <h1 className="text-xl font-bold text-gray-900 truncate">{preview.filename}</h1>
-          {preview.pageCount != null && (
-            <p className="text-sm text-gray-500">{preview.pageCount} page{preview.pageCount !== 1 ? 's' : ''}</p>
-          )}
-        </div>
-      </div>
- 
-      <div className="space-y-6">
-        {/* Extracted text preview */}
-        <section className="bg-white rounded-lg shadow">
-          <div className="px-6 py-4 border-b border-gray-100">
-            <h2 className="text-base font-semibold text-gray-900">Extracted Text</h2>
-          </div>
-          <div className="p-6">
-            {preview.extractedTextPreview ? (
-              <pre className="text-sm text-gray-800 whitespace-pre-wrap font-mono bg-gray-50 rounded-md p-4 max-h-96 overflow-auto">
-                {preview.extractedTextPreview}
-              </pre>
-            ) : (
-              <p className="text-sm text-gray-400 italic">No extracted text available yet.</p>
-            )}
-          </div>
-        </section>
- 
-        {/* Sections / page segmentation */}
-        <section className="bg-white rounded-lg shadow">
-          <div className="px-6 py-4 border-b border-gray-100">
-            <h2 className="text-base font-semibold text-gray-900">Sections / Page Segmentation</h2>
-          </div>
-          <div className="p-6">
-            {preview.sections && preview.sections.length > 0 ? (
-              <div className="space-y-3">
-                {preview.sections.map((section, i) => (
-                  <div key={i} className="rounded-md border border-gray-200 p-3">
-                    <p className="text-xs font-medium text-gray-500 mb-1">Section {i + 1}</p>
-                    <pre className="text-xs text-gray-700 whitespace-pre-wrap font-mono max-h-40 overflow-auto">
-                      {JSON.stringify(section, null, 2)}
-                    </pre>
-                  </div>
-                ))}
-              </div>
-            ) : (
-              <p className="text-sm text-gray-400 italic">No sections data available yet.</p>
-            )}
-          </div>
-        </section>
- 
-        {/* Sample chunks */}
-        <section className="bg-white rounded-lg shadow">
-          <div className="px-6 py-4 border-b border-gray-100">
-            <h2 className="text-base font-semibold text-gray-900">Sample Chunks</h2>
-          </div>
-          <div className="p-6">
-            {preview.sampleChunks && preview.sampleChunks.length > 0 ? (
-              <div className="space-y-3">
-                {preview.sampleChunks.map((chunk, i) => (
-                  <div key={i} className="rounded-md border border-gray-200 p-3">
-                    <p className="text-xs font-medium text-gray-500 mb-1">Chunk {i + 1}</p>
-                    <pre className="text-xs text-gray-700 whitespace-pre-wrap font-mono max-h-40 overflow-auto">
-                      {typeof chunk === 'string' ? chunk : JSON.stringify(chunk, null, 2)}
-                    </pre>
-                  </div>
-                ))}
-              </div>
-            ) : (
-              <p className="text-sm text-gray-400 italic">No chunk samples available yet.</p>
-            )}
-          </div>
-        </section>
-      </div>
-    </main>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/courses/[courseId]/index.html b/apps/web/coverage/lcov-report/src/app/courses/[courseId]/index.html deleted file mode 100644 index 5ee6fbc..0000000 --- a/apps/web/coverage/lcov-report/src/app/courses/[courseId]/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - Code coverage report for src/app/courses/[courseId] - - - - - - - - - -
-
-

All files src/app/courses/[courseId]

-
- -
- 0% - Statements - 0/44 -
- - -
- 0% - Branches - 0/15 -
- - -
- 0% - Functions - 0/12 -
- - -
- 0% - Lines - 0/42 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
layout.tsx -
-
0%0/90%0/40%0/30%0/9
page.tsx -
-
0%0/350%0/110%0/90%0/33
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/courses/[courseId]/layout.tsx.html b/apps/web/coverage/lcov-report/src/app/courses/[courseId]/layout.tsx.html deleted file mode 100644 index 996b6a2..0000000 --- a/apps/web/coverage/lcov-report/src/app/courses/[courseId]/layout.tsx.html +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - Code coverage report for src/app/courses/[courseId]/layout.tsx - - - - - - - - - -
-
-

All files / src/app/courses/[courseId] layout.tsx

-
- -
- 0% - Statements - 0/9 -
- - -
- 0% - Branches - 0/4 -
- - -
- 0% - Functions - 0/3 -
- - -
- 0% - Lines - 0/9 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-import Link from 'next/link';
-import { useParams, usePathname } from 'next/navigation';
-import { ReactNode } from 'react';
- 
-interface CourseLayoutProps {
-  children: ReactNode;
-}
- 
-export default function CourseLayout({ children }: CourseLayoutProps) {
-  const params = useParams();
-  const pathname = usePathname();
-  const courseId = params.courseId as string;
- 
-  const navItems = [
-    { href: `/courses/${courseId}`, label: 'Overview', exact: true },
-    { href: `/courses/${courseId}/study`, label: 'Study' },
-  ];
- 
-  function isActive(href: string, exact?: boolean) {
-    return exact ? pathname === href : pathname.startsWith(href);
-  }
- 
-  return (
-    <div className="min-h-screen bg-gray-50">
-      <header className="bg-white shadow-sm">
-        <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
-          <div className="flex items-center justify-between py-4">
-            <div className="flex items-center gap-4">
-              <Link
-                href="/courses"
-                className="text-sm text-gray-500 hover:text-gray-700 flex items-center gap-1"
-              >
-                <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor">
-                  <path strokeLinecap="round" strokeLinejoin="round" d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18" />
-                </svg>
-                Courses
-              </Link>
-            </div>
-          </div>
-          <nav className="-mb-px flex gap-6">
-            {navItems.map((item) => (
-              <Link
-                key={item.href}
-                href={item.href}
-                className={`pb-3 border-b-2 text-sm font-medium transition-colors ${
-                  isActive(item.href, item.exact)
-                    ? 'border-orange-500 text-orange-600'
-                    : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
-                }`}
-              >
-                {item.label}
-              </Link>
-            ))}
-          </nav>
-        </div>
-      </header>
-      {children}
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/courses/[courseId]/page.tsx.html b/apps/web/coverage/lcov-report/src/app/courses/[courseId]/page.tsx.html deleted file mode 100644 index 559b16e..0000000 --- a/apps/web/coverage/lcov-report/src/app/courses/[courseId]/page.tsx.html +++ /dev/null @@ -1,556 +0,0 @@ - - - - - - Code coverage report for src/app/courses/[courseId]/page.tsx - - - - - - - - - -
-
-

All files / src/app/courses/[courseId] page.tsx

-
- -
- 0% - Statements - 0/35 -
- - -
- 0% - Branches - 0/11 -
- - -
- 0% - Functions - 0/9 -
- - -
- 0% - Lines - 0/33 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-import { useEffect, useState, useCallback } from 'react';
-import { useParams, useRouter } from 'next/navigation';
-import { useSession } from 'next-auth/react';
-import { getCourse, getCourseLessons, type Course, type Lesson } from '@/lib/services/courses';
-import { DocumentList } from '@/components/courses/DocumentList';
-import { DocumentUpload } from '@/components/documents/DocumentUpload';
- 
-export default function CourseWorkspacePage() {
-  const params = useParams();
-  const router = useRouter();
-  const courseId = params.courseId as string;
-  const { data: session } = useSession();
-  const accessToken = (session?.user as any)?.accessToken;
- 
-  const [course, setCourse] = useState<Course | null>(null);
-  const [lessons, setLessons] = useState<Lesson[]>([]);
-  const [loading, setLoading] = useState(true);
-  const [error, setError] = useState<string | null>(null);
-  const [docRefreshKey, setDocRefreshKey] = useState(0);
- 
-  const refreshDocuments = useCallback(() => {
-    setDocRefreshKey((k) => k + 1);
-  }, []);
- 
-  function handleViewPreview(documentId: string) {
-    router.push(`/courses/${courseId}/documents/${documentId}/preview`);
-  }
- 
-  useEffect(() => {
-    async function load() {
-      try {
-        const [courseData, lessonsData] = await Promise.all([
-          getCourse(courseId, accessToken),
-          getCourseLessons(courseId, accessToken),
-        ]);
-        setCourse(courseData);
-        setLessons(lessonsData);
-      } catch (err) {
-        setError(err instanceof Error ? err.message : 'Failed to load course');
-      } finally {
-        setLoading(false);
-      }
-    }
- 
-    Iif (courseId) load();
-  }, [courseId, accessToken]);
- 
-  Iif (loading) {
-    return (
-      <main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
-        <div className="animate-pulse space-y-6">
-          <div className="h-8 w-1/3 bg-gray-200 rounded" />
-          <div className="h-4 w-2/3 bg-gray-100 rounded" />
-          <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
-            <div className="lg:col-span-2 bg-white rounded-lg shadow p-6 space-y-4">
-              <div className="h-5 w-1/4 bg-gray-200 rounded" />
-              {[1, 2, 3].map((i) => (
-                <div key={i} className="h-12 bg-gray-50 rounded" />
-              ))}
-            </div>
-            <div className="bg-white rounded-lg shadow p-6 space-y-4">
-              <div className="h-5 w-1/3 bg-gray-200 rounded" />
-              <div className="h-24 bg-gray-50 rounded" />
-            </div>
-          </div>
-        </div>
-      </main>
-    );
-  }
- 
-  Iif (error || !course) {
-    return (
-      <main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
-        <div className="rounded-lg border border-red-200 bg-red-50 p-6 text-center">
-          <p className="text-sm text-red-700">{error || 'Course not found'}</p>
-          <button
-            onClick={() => window.location.reload()}
-            className="mt-3 text-sm font-medium text-red-700 hover:text-red-800 underline"
-          >
-            Retry
-          </button>
-        </div>
-      </main>
-    );
-  }
- 
-  return (
-    <main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
-      <div className="mb-6">
-        <h1 className="text-2xl font-bold text-gray-900">{course.title}</h1>
-        {course.description && (
-          <p className="mt-1 text-gray-600">{course.description}</p>
-        )}
-      </div>
- 
-      <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
-        {/* Lessons panel */}
-        <div className="lg:col-span-2">
-          <div className="bg-white rounded-lg shadow">
-            <div className="px-6 py-4 border-b border-gray-100">
-              <h2 className="text-lg font-semibold text-gray-900">Lessons</h2>
-            </div>
-            <div className="p-6">
-              {lessons.length === 0 ? (
-                <div className="text-center py-8">
-                  <svg className="mx-auto h-10 w-10 text-gray-300" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
-                    <path strokeLinecap="round" strokeLinejoin="round" d="M4.26 10.147a60.438 60.438 0 00-.491 6.347A48.62 48.62 0 0112 20.904a48.62 48.62 0 018.232-4.41 60.46 60.46 0 00-.491-6.347m-15.482 0a50.636 50.636 0 00-2.658-.813A59.906 59.906 0 0112 3.493a59.903 59.903 0 0110.399 5.84c-.896.248-1.783.52-2.658.814m-15.482 0A50.717 50.717 0 0112 13.489a50.702 50.702 0 017.74-3.342" />
-                  </svg>
-                  <p className="mt-2 text-sm text-gray-500">No lessons available yet</p>
-                </div>
-              ) : (
-                <ul className="divide-y divide-gray-100">
-                  {lessons.map((lesson, index) => (
-                    <li key={lesson.id} className="flex items-center gap-4 py-3">
-                      <span className="flex-shrink-0 flex items-center justify-center h-8 w-8 rounded-full bg-orange-50 text-orange-600 text-sm font-semibold">
-                        {index + 1}
-                      </span>
-                      <div className="flex-1 min-w-0">
-                        <p className="text-sm font-medium text-gray-900">{lesson.title}</p>
-                      </div>
-                    </li>
-                  ))}
-                </ul>
-              )}
-            </div>
-          </div>
-        </div>
- 
-        {/* Documents sidebar */}
-        <div className="space-y-6">
-          <div className="bg-white rounded-lg shadow">
-            <div className="px-6 py-4 border-b border-gray-100">
-              <h2 className="text-lg font-semibold text-gray-900">Documents</h2>
-            </div>
-            <div className="p-6">
-              <DocumentUpload
-                courseId={courseId}
-                accessToken={accessToken}
-                onUploadComplete={refreshDocuments}
-              />
-              <div className="mt-4">
-                <DocumentList
-                  courseId={courseId}
-                  accessToken={accessToken}
-                  refreshKey={docRefreshKey}
-                  onViewPreview={handleViewPreview}
-                />
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-    </main>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/courses/[courseId]/study/index.html b/apps/web/coverage/lcov-report/src/app/courses/[courseId]/study/index.html deleted file mode 100644 index f7bea39..0000000 --- a/apps/web/coverage/lcov-report/src/app/courses/[courseId]/study/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for src/app/courses/[courseId]/study - - - - - - - - - -
-
-

All files src/app/courses/[courseId]/study

-
- -
- 0% - Statements - 0/22 -
- - -
- 0% - Branches - 0/2 -
- - -
- 0% - Functions - 0/3 -
- - -
- 0% - Lines - 0/21 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
page.tsx -
-
0%0/220%0/20%0/30%0/21
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/courses/[courseId]/study/page.tsx.html b/apps/web/coverage/lcov-report/src/app/courses/[courseId]/study/page.tsx.html deleted file mode 100644 index 9513c51..0000000 --- a/apps/web/coverage/lcov-report/src/app/courses/[courseId]/study/page.tsx.html +++ /dev/null @@ -1,238 +0,0 @@ - - - - - - Code coverage report for src/app/courses/[courseId]/study/page.tsx - - - - - - - - - -
-
-

All files / src/app/courses/[courseId]/study page.tsx

-
- -
- 0% - Statements - 0/22 -
- - -
- 0% - Branches - 0/2 -
- - -
- 0% - Functions - 0/3 -
- - -
- 0% - Lines - 0/21 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-import { useEffect, useState } from 'react';
-import { useParams } from 'next/navigation';
-import { useSession } from 'next-auth/react';
-import { getCourse, type Course } from '@/lib/services/courses';
-import { SplitPane } from '@/components/study/SplitPane';
-import { SourcePane } from '@/components/study/SourcePane';
-import { OutputPane } from '@/components/study/OutputPane';
- 
-export default function StudyPage() {
-  const params = useParams();
-  const courseId = params.courseId as string;
-  const { data: session } = useSession();
-  const accessToken = (session?.user as any)?.accessToken;
- 
-  const [course, setCourse] = useState<Course | null>(null);
-  const [loading, setLoading] = useState(true);
- 
-  useEffect(() => {
-    async function load() {
-      try {
-        const data = await getCourse(courseId, accessToken);
-        setCourse(data);
-      } catch {
-        // Course info is optional for the layout
-      } finally {
-        setLoading(false);
-      }
-    }
-    Iif (courseId) load();
-  }, [courseId, accessToken]);
- 
-  Iif (loading) {
-    return (
-      <div className="h-[calc(100vh-7rem)] flex items-center justify-center">
-        <div className="animate-spin rounded-full h-10 w-10 border-b-2 border-orange-600" />
-      </div>
-    );
-  }
- 
-  return (
-    <div className="h-[calc(100vh-7rem)]">
-      <SplitPane
-        left={<SourcePane courseTitle={course?.title} />}
-        right={<OutputPane />}
-        defaultLeftPercent={50}
-      />
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/courses/index.html b/apps/web/coverage/lcov-report/src/app/courses/index.html deleted file mode 100644 index 8442eba..0000000 --- a/apps/web/coverage/lcov-report/src/app/courses/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for src/app/courses - - - - - - - - - -
-
-

All files src/app/courses

-
- -
- 0% - Statements - 0/28 -
- - -
- 0% - Branches - 0/10 -
- - -
- 0% - Functions - 0/6 -
- - -
- 0% - Lines - 0/27 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
page.tsx -
-
0%0/280%0/100%0/60%0/27
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/courses/page.tsx.html b/apps/web/coverage/lcov-report/src/app/courses/page.tsx.html deleted file mode 100644 index b1f303a..0000000 --- a/apps/web/coverage/lcov-report/src/app/courses/page.tsx.html +++ /dev/null @@ -1,397 +0,0 @@ - - - - - - Code coverage report for src/app/courses/page.tsx - - - - - - - - - -
-
-

All files / src/app/courses page.tsx

-
- -
- 0% - Statements - 0/28 -
- - -
- 0% - Branches - 0/10 -
- - -
- 0% - Functions - 0/6 -
- - -
- 0% - Lines - 0/27 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-import { useEffect, useState } from 'react';
-import { useSession } from 'next-auth/react';
-import { useRouter } from 'next/navigation';
-import Link from 'next/link';
-import { getCourses, type Course } from '@/lib/services/courses';
-import { CourseCard } from '@/components/courses/CourseCard';
- 
-export default function CoursesPage() {
-  const { data: session, status } = useSession();
-  const router = useRouter();
-  const [courses, setCourses] = useState<Course[]>([]);
-  const [loading, setLoading] = useState(true);
-  const [error, setError] = useState<string | null>(null);
- 
-  useEffect(() => {
-    Iif (status === 'unauthenticated') {
-      router.push('/login');
-      return;
-    }
-    Iif (status !== 'authenticated') return;
- 
-    async function fetchCourses() {
-      try {
-        const data = await getCourses(0, 100, (session?.user as any)?.accessToken);
-        setCourses(data);
-      } catch (err) {
-        setError(err instanceof Error ? err.message : 'Failed to load courses');
-      } finally {
-        setLoading(false);
-      }
-    }
- 
-    fetchCourses();
-  }, [status, session, router]);
- 
-  Iif (status === 'loading' || (status === 'authenticated' && loading)) {
-    return (
-      <div className="min-h-screen bg-gray-50">
-        <header className="bg-white shadow-sm">
-          <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
-            <div className="h-7 w-48 bg-gray-200 rounded animate-pulse" />
-          </div>
-        </header>
-        <main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
-          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
-            {[1, 2, 3].map((i) => (
-              <div key={i} className="bg-white rounded-lg shadow p-6 animate-pulse">
-                <div className="h-5 w-3/4 bg-gray-200 rounded" />
-                <div className="mt-3 h-4 w-full bg-gray-100 rounded" />
-                <div className="mt-1 h-4 w-2/3 bg-gray-100 rounded" />
-                <div className="mt-5 h-4 w-1/3 bg-orange-100 rounded" />
-              </div>
-            ))}
-          </div>
-        </main>
-      </div>
-    );
-  }
- 
-  return (
-    <div className="min-h-screen bg-gray-50">
-      <header className="bg-white shadow-sm">
-        <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex justify-between items-center">
-          <div>
-            <Link href="/dashboard" className="text-sm text-gray-500 hover:text-gray-700">
-              &larr; Dashboard
-            </Link>
-            <h1 className="text-2xl font-bold text-gray-900 mt-1">Courses</h1>
-          </div>
-        </div>
-      </header>
- 
-      <main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
-        {error ? (
-          <div className="rounded-lg border border-red-200 bg-red-50 p-6 text-center">
-            <p className="text-sm text-red-700">{error}</p>
-            <button
-              onClick={() => window.location.reload()}
-              className="mt-3 text-sm font-medium text-red-700 hover:text-red-800 underline"
-            >
-              Retry
-            </button>
-          </div>
-        ) : courses.length === 0 ? (
-          <div className="text-center py-16">
-            <svg className="mx-auto h-12 w-12 text-gray-300" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
-              <path strokeLinecap="round" strokeLinejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25" />
-            </svg>
-            <h3 className="mt-4 text-lg font-medium text-gray-900">No courses available</h3>
-            <p className="mt-1 text-sm text-gray-500">Courses will appear here once they are created.</p>
-          </div>
-        ) : (
-          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
-            {courses.map((course) => (
-              <CourseCard key={course.id} course={course} />
-            ))}
-          </div>
-        )}
-      </main>
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/dashboard/index.html b/apps/web/coverage/lcov-report/src/app/dashboard/index.html deleted file mode 100644 index 33f75fc..0000000 --- a/apps/web/coverage/lcov-report/src/app/dashboard/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for src/app/dashboard - - - - - - - - - -
-
-

All files src/app/dashboard

-
- -
- 0% - Statements - 0/24 -
- - -
- 0% - Branches - 0/11 -
- - -
- 0% - Functions - 0/4 -
- - -
- 0% - Lines - 0/23 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
page.tsx -
-
0%0/240%0/110%0/40%0/23
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/dashboard/page.tsx.html b/apps/web/coverage/lcov-report/src/app/dashboard/page.tsx.html deleted file mode 100644 index afca36d..0000000 --- a/apps/web/coverage/lcov-report/src/app/dashboard/page.tsx.html +++ /dev/null @@ -1,508 +0,0 @@ - - - - - - Code coverage report for src/app/dashboard/page.tsx - - - - - - - - - -
-
-

All files / src/app/dashboard page.tsx

-
- -
- 0% - Statements - 0/24 -
- - -
- 0% - Branches - 0/11 -
- - -
- 0% - Functions - 0/4 -
- - -
- 0% - Lines - 0/23 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-import { useEffect, useState } from 'react';
-import { signOut, useSession } from 'next-auth/react';
-import { useRouter } from 'next/navigation';
-import Link from 'next/link';
-import { getCourses, type Course } from '@/lib/services/courses';
- 
-export default function DashboardPage() {
-  const { data: session, status } = useSession();
-  const router = useRouter();
-  const [courses, setCourses] = useState<Course[]>([]);
-  const [coursesLoading, setCoursesLoading] = useState(true);
- 
-  useEffect(() => {
-    Iif (status !== 'authenticated') return;
- 
-    async function fetchCourses() {
-      try {
-        const data = await getCourses(0, 100, (session?.user as any)?.accessToken);
-        setCourses(data);
-      } catch {
-        // Non-critical — dashboard still usable without course count
-      } finally {
-        setCoursesLoading(false);
-      }
-    }
- 
-    fetchCourses();
-  }, [status, session]);
- 
-  Iif (status === 'loading') {
-    return (
-      <div className="min-h-screen flex items-center justify-center bg-gray-50">
-        <div className="text-center">
-          <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-orange-600 mx-auto"></div>
-          <p className="mt-4 text-gray-600">Loading...</p>
-        </div>
-      </div>
-    );
-  }
- 
-  Iif (status === 'unauthenticated') {
-    router.push('/login');
-    return null;
-  }
- 
-  const handleSignOut = async () => {
-    await signOut({ callbackUrl: '/login' });
-  };
- 
-  return (
-    <div className="min-h-screen bg-gray-50">
-      <header className="bg-white shadow-sm">
-        <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex justify-between items-center">
-          <h1 className="text-2xl font-bold text-gray-900">BitPolito Academy</h1>
-          <div className="flex items-center space-x-4">
-            <span className="text-sm text-gray-600">{session?.user?.email}</span>
-            <button
-              onClick={handleSignOut}
-              className="px-4 py-2 text-sm font-medium text-white bg-orange-600 rounded-md hover:bg-orange-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-orange-500"
-            >
-              Sign out
-            </button>
-          </div>
-        </div>
-      </header>
- 
-      <main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
-        <div className="bg-white rounded-lg shadow p-6">
-          <h2 className="text-xl font-semibold text-gray-900 mb-4">
-            Welcome, {(session?.user as any)?.displayName || session?.user?.email}!
-          </h2>
- 
-          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mt-6">
-            {/* User Info Card */}
-            <div className="bg-gray-50 rounded-lg p-4">
-              <h3 className="text-lg font-medium text-gray-900 mb-2">Your Profile</h3>
-              <dl className="space-y-2">
-                <div>
-                  <dt className="text-sm text-gray-500">Email</dt>
-                  <dd className="text-sm font-medium text-gray-900">{session?.user?.email}</dd>
-                </div>
-                <div>
-                  <dt className="text-sm text-gray-500">Display Name</dt>
-                  <dd className="text-sm font-medium text-gray-900">
-                    {(session?.user as any)?.displayName || 'Not set'}
-                  </dd>
-                </div>
-                <div>
-                  <dt className="text-sm text-gray-500">Role</dt>
-                  <dd className="text-sm font-medium text-gray-900 capitalize">
-                    {(session?.user as any)?.role || 'Student'}
-                  </dd>
-                </div>
-              </dl>
-            </div>
- 
-            {/* Quick Stats Card */}
-            <div className="bg-gray-50 rounded-lg p-4">
-              <h3 className="text-lg font-medium text-gray-900 mb-2">Your Progress</h3>
-              <div className="space-y-3">
-                <div className="flex justify-between items-center">
-                  <span className="text-sm text-gray-600">Available Courses</span>
-                  <span className="text-lg font-semibold text-orange-600">
-                    {coursesLoading ? (
-                      <span className="inline-block h-5 w-6 bg-gray-200 rounded animate-pulse" />
-                    ) : (
-                      courses.length
-                    )}
-                  </span>
-                </div>
-                <div className="flex justify-between items-center">
-                  <span className="text-sm text-gray-600">Courses Completed</span>
-                  <span className="text-lg font-semibold text-green-600">0</span>
-                </div>
-                <div className="flex justify-between items-center">
-                  <span className="text-sm text-gray-600">Certificates Earned</span>
-                  <span className="text-lg font-semibold text-blue-600">0</span>
-                </div>
-              </div>
-            </div>
- 
-            {/* Quick Actions Card */}
-            <div className="bg-gray-50 rounded-lg p-4">
-              <h3 className="text-lg font-medium text-gray-900 mb-2">Quick Actions</h3>
-              <div className="space-y-2">
-                <Link
-                  href="/courses"
-                  className="block w-full px-4 py-2 text-center text-sm font-medium text-white bg-orange-600 rounded-md hover:bg-orange-700"
-                >
-                  Browse Courses
-                </Link>
-              </div>
-            </div>
-          </div>
-        </div>
-      </main>
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/index.html b/apps/web/coverage/lcov-report/src/app/index.html deleted file mode 100644 index 40cc476..0000000 --- a/apps/web/coverage/lcov-report/src/app/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - Code coverage report for src/app - - - - - - - - - -
-
-

All files src/app

-
- -
- 0% - Statements - 0/18 -
- - -
- 0% - Branches - 0/6 -
- - -
- 0% - Functions - 0/3 -
- - -
- 0% - Lines - 0/17 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
layout.tsx -
-
0%0/5100%0/00%0/10%0/4
page.tsx -
-
0%0/130%0/60%0/20%0/13
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/layout.tsx.html b/apps/web/coverage/lcov-report/src/app/layout.tsx.html deleted file mode 100644 index e199ab4..0000000 --- a/apps/web/coverage/lcov-report/src/app/layout.tsx.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - Code coverage report for src/app/layout.tsx - - - - - - - - - -
-
-

All files / src/app layout.tsx

-
- -
- 0% - Statements - 0/5 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/4 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import type { Metadata } from 'next';
-import './globals.css';
-import { AuthProvider } from '@/components/providers/AuthProvider';
- 
-export const metadata: Metadata = {
-  title: 'BitPolito Academy',
-  description: 'Learn Bitcoin with interactive courses',
-  viewport: 'width=device-width, initial-scale=1',
-};
- 
-export default function RootLayout({ children }: { children: React.ReactNode }) {
-  return (
-    <html lang="en">
-      <body>
-        <AuthProvider>{children}</AuthProvider>
-      </body>
-    </html>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/app/page.tsx.html b/apps/web/coverage/lcov-report/src/app/page.tsx.html deleted file mode 100644 index 82d816b..0000000 --- a/apps/web/coverage/lcov-report/src/app/page.tsx.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - Code coverage report for src/app/page.tsx - - - - - - - - - -
-
-

All files / src/app page.tsx

-
- -
- 0% - Statements - 0/13 -
- - -
- 0% - Branches - 0/6 -
- - -
- 0% - Functions - 0/2 -
- - -
- 0% - Lines - 0/13 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-import { useEffect } from 'react';
-import { useRouter } from 'next/navigation';
-import { useSession } from 'next-auth/react';
- 
-export default function Home() {
-  const router = useRouter();
-  const { status } = useSession();
- 
-  useEffect(() => {
-    if (status === 'unauthenticated') {
-      router.push('/login');
-    } else Iif (status === 'authenticated') {
-      router.push('/dashboard');
-    }
-  }, [status, router]);
- 
-  Iif (status === 'loading' || status === 'unauthenticated') {
-    return (
-      <main className="flex min-h-screen flex-col items-center justify-center p-24 bg-gradient-to-b from-dark to-light">
-        <div className="text-center">
-          <p className="text-gray-500">Redirecting...</p>
-        </div>
-      </main>
-    );
-  }
- 
-  return null;
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/components/courses/CourseCard.tsx.html b/apps/web/coverage/lcov-report/src/components/courses/CourseCard.tsx.html deleted file mode 100644 index 57f4b89..0000000 --- a/apps/web/coverage/lcov-report/src/components/courses/CourseCard.tsx.html +++ /dev/null @@ -1,220 +0,0 @@ - - - - - - Code coverage report for src/components/courses/CourseCard.tsx - - - - - - - - - -
-
-

All files / src/components/courses CourseCard.tsx

-
- -
- 0% - Statements - 0/2 -
- - -
- 0% - Branches - 0/1 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/2 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-import Link from 'next/link';
-import type { Course } from '@/lib/services/courses';
- 
-interface CourseCardProps {
-  course: Course;
-}
- 
-export function CourseCard({ course }: CourseCardProps) {
-  return (
-    <Link
-      href={`/courses/${course.id}`}
-      className="block bg-white rounded-lg shadow hover:shadow-md transition-shadow border border-gray-100"
-    >
-      <div className="p-6">
-        <div className="flex items-start justify-between">
-          <div className="flex-1 min-w-0">
-            <h3 className="text-lg font-semibold text-gray-900 truncate">
-              {course.title}
-            </h3>
-            {course.description && (
-              <p className="mt-2 text-sm text-gray-600 line-clamp-2">
-                {course.description}
-              </p>
-            )}
-          </div>
-          <div className="ml-4 flex-shrink-0">
-            <span className="inline-flex items-center justify-center h-10 w-10 rounded-lg bg-orange-100 text-orange-600">
-              <svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
-                <path strokeLinecap="round" strokeLinejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25" />
-              </svg>
-            </span>
-          </div>
-        </div>
-        <div className="mt-4 flex items-center text-sm text-orange-600 font-medium">
-          Open workspace
-          <svg className="ml-1 h-4 w-4" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor">
-            <path strokeLinecap="round" strokeLinejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3" />
-          </svg>
-        </div>
-      </div>
-    </Link>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/components/courses/DocumentList.tsx.html b/apps/web/coverage/lcov-report/src/components/courses/DocumentList.tsx.html deleted file mode 100644 index 42f8761..0000000 --- a/apps/web/coverage/lcov-report/src/components/courses/DocumentList.tsx.html +++ /dev/null @@ -1,808 +0,0 @@ - - - - - - Code coverage report for src/components/courses/DocumentList.tsx - - - - - - - - - -
-
-

All files / src/components/courses DocumentList.tsx

-
- -
- 0% - Statements - 0/57 -
- - -
- 0% - Branches - 0/30 -
- - -
- 0% - Functions - 0/16 -
- - -
- 0% - Lines - 0/50 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-import { useCallback, useEffect, useRef, useState } from 'react';
-import { getDocumentListRows } from '@/lib/api/documents';
-import type { DocumentListRow } from '@/lib/api/types';
-import { ProcessingIndicator } from './ProcessingIndicator';
-import { DocumentProcessingPanel } from '@/components/documents/DocumentProcessingPanel';
- 
-interface DocumentListProps {
-  courseId: string;
-  accessToken?: string;
-  refreshKey?: number;
-  onViewPreview?: (documentId: string) => void;
-}
- 
-const AUTO_POLL_INTERVAL_MS = 8000;
- 
-function formatFileSize(bytes: number): string {
-  Iif (bytes < 1024) return `${bytes} B`;
-  Iif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
-  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
-}
- 
-function formatTime(iso: string): string {
-  try {
-    return new Date(iso).toLocaleString(undefined, {
-      month: 'short',
-      day: 'numeric',
-      hour: '2-digit',
-      minute: '2-digit',
-    });
-  } catch {
-    return iso;
-  }
-}
- 
-export function DocumentList({
-  courseId,
-  accessToken,
-  refreshKey = 0,
-  onViewPreview,
-}: DocumentListProps) {
-  const [documents, setDocuments] = useState<DocumentListRow[]>([]);
-  const [loading, setLoading] = useState(true);
-  const [error, setError] = useState<string | null>(null);
-  const [refreshing, setRefreshing] = useState(false);
-  const [expandedId, setExpandedId] = useState<string | null>(null);
-  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);
- 
-  const fetchDocuments = useCallback(
-    async (silent = false) => {
-      try {
-        Iif (!silent) setError(null);
-        const rows = await getDocumentListRows(courseId, accessToken);
-        setDocuments(rows);
-      } catch (err) {
-        const message = err instanceof Error ? err.message : 'Failed to load documents';
-        if (message.includes('Request failed (404)') || message.includes('Request failed (50')) {
-          setDocuments([]);
-          setError(null);
-        } else Iif (!silent) {
-          setError(message);
-        }
-      } finally {
-        setLoading(false);
-        setRefreshing(false);
-      }
-    },
-    [courseId, accessToken],
-  );
- 
-  useEffect(() => {
-    fetchDocuments();
-  }, [fetchDocuments, refreshKey]);
- 
-  useEffect(() => {
-    const hasInProgress = documents.some((d) => !d.isTerminal);
-    Iif (hasInProgress) {
-      pollRef.current = setInterval(() => fetchDocuments(true), AUTO_POLL_INTERVAL_MS);
-    }
-    return () => {
-      Iif (pollRef.current) clearInterval(pollRef.current);
-    };
-  }, [documents, fetchDocuments]);
- 
-  function handleRefresh() {
-    setRefreshing(true);
-    fetchDocuments();
-  }
- 
-  function toggleExpand(id: string) {
-    setExpandedId((prev) => (prev === id ? null : id));
-  }
- 
-  Iif (loading) {
-    return (
-      <div className="space-y-3">
-        {[1, 2, 3].map((i) => (
-          <div key={i} className="animate-pulse flex items-center gap-3 p-3 rounded-lg bg-gray-50">
-            <div className="h-8 w-8 rounded bg-gray-200" />
-            <div className="flex-1 space-y-1.5">
-              <div className="h-3 w-2/3 rounded bg-gray-200" />
-              <div className="h-2.5 w-1/4 rounded bg-gray-200" />
-            </div>
-          </div>
-        ))}
-      </div>
-    );
-  }
- 
-  Iif (error) {
-    return (
-      <div className="rounded-lg border border-red-200 bg-red-50 p-4">
-        <p className="text-sm text-red-700">{error}</p>
-        <button
-          onClick={() => fetchDocuments()}
-          className="mt-2 text-sm font-medium text-red-700 hover:text-red-800 underline"
-        >
-          Retry
-        </button>
-      </div>
-    );
-  }
- 
-  Iif (documents.length === 0) {
-    return (
-      <div className="text-center py-8 px-4">
-        <svg
-          className="mx-auto h-10 w-10 text-gray-300"
-          fill="none"
-          viewBox="0 0 24 24"
-          strokeWidth={1.5}
-          stroke="currentColor"
-        >
-          <path
-            strokeLinecap="round"
-            strokeLinejoin="round"
-            d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m6.75 12H9.75m3 0h.008v.008H12.75v-.008zM12 18.75h.008v.008H12v-.008zm-3 0h.008v.008H9v-.008zm6-6h.008v.008h-.008v-.008zm-3 0h.008v.008H12v-.008zm-3 0h.008v.008H9v-.008z"
-          />
-        </svg>
-        <p className="mt-2 text-sm text-gray-500">No documents uploaded yet</p>
-        <p className="text-xs text-gray-400">Upload slides, notes, or reference material to get started</p>
-      </div>
-    );
-  }
- 
-  return (
-    <div>
-      <div className="flex items-center justify-between mb-3">
-        <p className="text-xs text-gray-500">
-          {documents.length} document{documents.length !== 1 ? 's' : ''}
-        </p>
-        <button
-          onClick={handleRefresh}
-          disabled={refreshing}
-          className="inline-flex items-center gap-1 text-xs text-gray-500 hover:text-gray-700 disabled:opacity-50"
-          title="Refresh list"
-        >
-          <svg
-            className={`h-3.5 w-3.5 ${refreshing ? 'animate-spin' : ''}`}
-            fill="none"
-            viewBox="0 0 24 24"
-            strokeWidth={2}
-            stroke="currentColor"
-          >
-            <path
-              strokeLinecap="round"
-              strokeLinejoin="round"
-              d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182"
-            />
-          </svg>
-          {refreshing ? 'Refreshing...' : 'Refresh'}
-        </button>
-      </div>
- 
-      <ul className="divide-y divide-gray-100">
-        {documents.map((doc) => {
-          const isExpanded = expandedId === doc.id;
-          return (
-            <li key={doc.id} className="py-2 px-1">
-              <button
-                type="button"
-                onClick={() => toggleExpand(doc.id)}
-                className="w-full text-left rounded-md hover:bg-gray-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-orange-400"
-                aria-expanded={isExpanded}
-              >
-                <div className="flex items-start gap-3">
-                  {/* Expand chevron */}
-                  <svg
-                    className={`mt-1 h-4 w-4 flex-shrink-0 text-gray-400 transition-transform ${isExpanded ? 'rotate-90' : ''}`}
-                    fill="none"
-                    viewBox="0 0 24 24"
-                    strokeWidth={2}
-                    stroke="currentColor"
-                  >
-                    <path strokeLinecap="round" strokeLinejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
-                  </svg>
- 
-                  {/* File type badge */}
-                  <span className="flex-shrink-0 mt-0.5 inline-flex items-center justify-center h-8 w-8 rounded-md bg-gray-100 text-[10px] font-bold text-gray-500 uppercase">
-                    {doc.fileType}
-                  </span>
- 
-                  <div className="flex-1 min-w-0">
-                    <div className="flex items-center gap-2">
-                      <p className="text-sm font-medium text-gray-900 truncate">{doc.filename}</p>
-                      <ProcessingIndicator status={doc.status} stage={doc.processingStage} />
-                    </div>
- 
-                    <div className="mt-0.5 flex items-center gap-3 text-xs text-gray-500">
-                      <span>{formatFileSize(doc.size)}</span>
-                      <span title="Uploaded">{formatTime(doc.createdAt)}</span>
-                      <span title="Last updated">updated {formatTime(doc.updatedAt)}</span>
-                    </div>
- 
-                    {doc.status === 'error' && doc.errorMessage && (
-                      <p className="mt-1 text-xs text-red-600 truncate" title={doc.errorMessage}>
-                        {doc.errorMessage}
-                      </p>
-                    )}
-                  </div>
-                </div>
-              </button>
- 
-              {/* Expandable detail panel (U-05) */}
-              {isExpanded && (
-                <div className="mt-2 ml-7">
-                  <DocumentProcessingPanel
-                    documentId={doc.id}
-                    accessToken={accessToken}
-                    onViewPreview={onViewPreview}
-                  />
-                </div>
-              )}
-            </li>
-          );
-        })}
-      </ul>
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/components/courses/ProcessingIndicator.tsx.html b/apps/web/coverage/lcov-report/src/components/courses/ProcessingIndicator.tsx.html deleted file mode 100644 index 9a7497e..0000000 --- a/apps/web/coverage/lcov-report/src/components/courses/ProcessingIndicator.tsx.html +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - Code coverage report for src/components/courses/ProcessingIndicator.tsx - - - - - - - - - -
-
-

All files / src/components/courses ProcessingIndicator.tsx

-
- -
- 0% - Statements - 0/5 -
- - -
- 0% - Branches - 0/8 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/5 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-import type { DocumentStatus, ProcessingStage } from '@/lib/api/types';
- 
-interface ProcessingIndicatorProps {
-  status: DocumentStatus;
-  stage?: ProcessingStage;
-  className?: string;
-}
- 
-const STATUS_CONFIG: Record<DocumentStatus, { label: string; bg: string; text: string; dot: string }> = {
-  uploading: {
-    label: 'Uploading',
-    bg: 'bg-blue-50',
-    text: 'text-blue-700',
-    dot: 'bg-blue-500 animate-pulse',
-  },
-  processing: {
-    label: 'Processing',
-    bg: 'bg-yellow-50',
-    text: 'text-yellow-700',
-    dot: 'bg-yellow-500 animate-pulse',
-  },
-  ready: {
-    label: 'Ready',
-    bg: 'bg-green-50',
-    text: 'text-green-700',
-    dot: 'bg-green-500',
-  },
-  error: {
-    label: 'Error',
-    bg: 'bg-red-50',
-    text: 'text-red-700',
-    dot: 'bg-red-500',
-  },
-};
- 
-const STAGE_LABELS: Record<ProcessingStage, string> = {
-  queued: 'Queued',
-  uploading: 'Uploading',
-  parsing: 'Parsing',
-  normalizing: 'Normalizing',
-  chunking: 'Chunking',
-  indexing: 'Indexing',
-  done: 'Done',
-  error: 'Error',
-};
- 
-export function ProcessingIndicator({ status, stage, className = '' }: ProcessingIndicatorProps) {
-  const config = STATUS_CONFIG[status];
-  const stageLabel = stage && stage !== 'done' && stage !== 'error' ? STAGE_LABELS[stage] : null;
- 
-  return (
-    <span
-      className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium ${config.bg} ${config.text} ${className}`}
-    >
-      <span className={`h-1.5 w-1.5 rounded-full ${config.dot}`} />
-      {config.label}
-      {stageLabel && status === 'processing' && (
-        <span className="opacity-75">· {stageLabel}</span>
-      )}
-    </span>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/components/courses/index.html b/apps/web/coverage/lcov-report/src/components/courses/index.html deleted file mode 100644 index 136f774..0000000 --- a/apps/web/coverage/lcov-report/src/components/courses/index.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - Code coverage report for src/components/courses - - - - - - - - - -
-
-

All files src/components/courses

-
- -
- 0% - Statements - 0/64 -
- - -
- 0% - Branches - 0/39 -
- - -
- 0% - Functions - 0/18 -
- - -
- 0% - Lines - 0/57 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
CourseCard.tsx -
-
0%0/20%0/10%0/10%0/2
DocumentList.tsx -
-
0%0/570%0/300%0/160%0/50
ProcessingIndicator.tsx -
-
0%0/50%0/80%0/10%0/5
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/components/documents/DocumentProcessingPanel.tsx.html b/apps/web/coverage/lcov-report/src/components/documents/DocumentProcessingPanel.tsx.html deleted file mode 100644 index 0ebb0b5..0000000 --- a/apps/web/coverage/lcov-report/src/components/documents/DocumentProcessingPanel.tsx.html +++ /dev/null @@ -1,409 +0,0 @@ - - - - - - Code coverage report for src/components/documents/DocumentProcessingPanel.tsx - - - - - - - - - -
-
-

All files / src/components/documents DocumentProcessingPanel.tsx

-
- -
- 0% - Statements - 0/20 -
- - -
- 0% - Branches - 0/10 -
- - -
- 0% - Functions - 0/5 -
- - -
- 0% - Lines - 0/19 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-import { useCallback, useEffect, useState } from 'react';
-import { getDocumentDetailView } from '@/lib/api/documents';
-import type { DocumentDetailView } from '@/lib/api/types';
- 
-interface DocumentProcessingPanelProps {
-  documentId: string;
-  accessToken?: string;
-  onViewPreview?: (documentId: string) => void;
-}
- 
-function DetailRow({ label, value }: { label: string; value: React.ReactNode }) {
-  return (
-    <div className="flex items-start justify-between py-1.5">
-      <dt className="text-xs font-medium text-gray-500 w-36 flex-shrink-0">{label}</dt>
-      <dd className="text-xs text-gray-900 text-right">{value ?? <span className="text-gray-400">N/A</span>}</dd>
-    </div>
-  );
-}
- 
-export function DocumentProcessingPanel({
-  documentId,
-  accessToken,
-  onViewPreview,
-}: DocumentProcessingPanelProps) {
-  const [detail, setDetail] = useState<DocumentDetailView | null>(null);
-  const [loading, setLoading] = useState(true);
-  const [error, setError] = useState<string | null>(null);
- 
-  const load = useCallback(async () => {
-    try {
-      setError(null);
-      const data = await getDocumentDetailView(documentId, accessToken);
-      setDetail(data);
-    } catch (err) {
-      setError(err instanceof Error ? err.message : 'Failed to load document details');
-    } finally {
-      setLoading(false);
-    }
-  }, [documentId, accessToken]);
- 
-  useEffect(() => {
-    load();
-  }, [load]);
- 
-  Iif (loading) {
-    return (
-      <div className="animate-pulse space-y-2 py-3 px-4">
-        <div className="h-3 w-2/3 rounded bg-gray-200" />
-        <div className="h-3 w-1/2 rounded bg-gray-200" />
-        <div className="h-3 w-3/4 rounded bg-gray-200" />
-      </div>
-    );
-  }
- 
-  Iif (error) {
-    return (
-      <div className="py-3 px-4">
-        <p className="text-xs text-red-600">{error}</p>
-        <button onClick={load} className="mt-1 text-xs text-red-700 hover:text-red-800 underline">
-          Retry
-        </button>
-      </div>
-    );
-  }
- 
-  Iif (!detail) return null;
- 
-  return (
-    <div className="py-3 px-4 bg-gray-50 rounded-md space-y-1">
-      <dl className="divide-y divide-gray-100">
-        <DetailRow label="Raw status" value={detail.status} />
-        <DetailRow label="Processing stage" value={detail.processingStage} />
-        <DetailRow label="Parser used" value={detail.parserUsed} />
-        <DetailRow label="Page / slide count" value={detail.pageCount} />
-        <DetailRow label="Chunk count" value={detail.chunkCount} />
-        <DetailRow label="Indexing status" value={detail.indexingStatus} />
-        {detail.errorMessage && (
-          <DetailRow
-            label="Processing errors"
-            value={<span className="text-red-600">{detail.errorMessage}</span>}
-          />
-        )}
-        {detail.normalizedMetadata && (
-          <div className="py-1.5">
-            <dt className="text-xs font-medium text-gray-500 mb-1">Normalized metadata</dt>
-            <dd className="text-[11px] font-mono bg-white rounded border border-gray-200 p-2 max-h-32 overflow-auto whitespace-pre-wrap">
-              {JSON.stringify(detail.normalizedMetadata, null, 2)}
-            </dd>
-          </div>
-        )}
-      </dl>
- 
-      {onViewPreview && detail.status === 'ready' && (
-        <button
-          onClick={() => onViewPreview(detail.id)}
-          className="mt-2 inline-flex items-center gap-1 text-xs font-medium text-orange-600 hover:text-orange-700"
-        >
-          View extracted content
-          <svg className="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor">
-            <path strokeLinecap="round" strokeLinejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3" />
-          </svg>
-        </button>
-      )}
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/components/documents/DocumentRow.tsx.html b/apps/web/coverage/lcov-report/src/components/documents/DocumentRow.tsx.html deleted file mode 100644 index 9b30ce6..0000000 --- a/apps/web/coverage/lcov-report/src/components/documents/DocumentRow.tsx.html +++ /dev/null @@ -1,259 +0,0 @@ - - - - - - Code coverage report for src/components/documents/DocumentRow.tsx - - - - - - - - - -
-
-

All files / src/components/documents DocumentRow.tsx

-
- -
- 0% - Statements - 0/17 -
- - -
- 0% - Branches - 0/3 -
- - -
- 0% - Functions - 0/3 -
- - -
- 0% - Lines - 0/14 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-import { useState } from 'react';
-import type { DocumentListRow } from '@/lib/api/types';
-import { deleteDocument } from '@/lib/api/documents';
-import { ProcessingIndicator } from '@/components/courses/ProcessingIndicator';
- 
-interface DocumentRowProps {
-  document: DocumentListRow;
-  accessToken?: string;
-  onDeleted?: () => void;
-}
- 
-function formatFileSize(bytes: number): string {
-  Iif (bytes < 1024) return `${bytes} B`;
-  Iif (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
-  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
-}
- 
-export function DocumentRow({ document: doc, accessToken, onDeleted }: DocumentRowProps) {
-  const [deleting, setDeleting] = useState(false);
- 
-  async function handleDelete() {
-    Iif (!confirm(`Delete "${doc.filename}"?`)) return;
-    setDeleting(true);
-    try {
-      await deleteDocument(doc.id, accessToken);
-      onDeleted?.();
-    } catch {
-      setDeleting(false);
-    }
-  }
- 
-  return (
-    <div className="flex items-center gap-3 py-3 px-1 group">
-      <div className="flex-shrink-0">
-        <svg className="h-7 w-7 text-gray-400" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
-          <path strokeLinecap="round" strokeLinejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" />
-        </svg>
-      </div>
-      <div className="flex-1 min-w-0">
-        <p className="text-sm font-medium text-gray-900 truncate">{doc.filename}</p>
-        <p className="text-xs text-gray-500">{formatFileSize(doc.size)}</p>
-      </div>
-      <ProcessingIndicator status={doc.status} />
-      <button
-        onClick={handleDelete}
-        disabled={deleting}
-        className="opacity-0 group-hover:opacity-100 transition-opacity p-1 rounded hover:bg-red-50 text-gray-400 hover:text-red-500 disabled:opacity-50"
-        title="Delete document"
-      >
-        <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
-          <path strokeLinecap="round" strokeLinejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
-        </svg>
-      </button>
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/components/documents/DocumentUpload.tsx.html b/apps/web/coverage/lcov-report/src/components/documents/DocumentUpload.tsx.html deleted file mode 100644 index 8e41660..0000000 --- a/apps/web/coverage/lcov-report/src/components/documents/DocumentUpload.tsx.html +++ /dev/null @@ -1,541 +0,0 @@ - - - - - - Code coverage report for src/components/documents/DocumentUpload.tsx - - - - - - - - - -
-
-

All files / src/components/documents DocumentUpload.tsx

-
- -
- 0% - Statements - 0/57 -
- - -
- 0% - Branches - 0/14 -
- - -
- 0% - Functions - 0/16 -
- - -
- 0% - Lines - 0/48 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-import { useCallback, useRef, useState } from 'react';
-import { uploadDocument, pollDocumentUntilTerminal } from '@/lib/api/documents';
- 
-interface DocumentUploadProps {
-  courseId: string;
-  accessToken?: string;
-  onUploadComplete?: () => void;
-}
- 
-interface UploadJob {
-  file: File;
-  progress: 'uploading' | 'processing' | 'done' | 'error';
-  errorMessage?: string;
-}
- 
-export function DocumentUpload({ courseId, accessToken, onUploadComplete }: DocumentUploadProps) {
-  const [jobs, setJobs] = useState<UploadJob[]>([]);
-  const [isDragOver, setIsDragOver] = useState(false);
-  const inputRef = useRef<HTMLInputElement>(null);
- 
-  const handleFiles = useCallback(
-    async (files: FileList | File[]) => {
-      const fileArray = Array.from(files);
-      Iif (fileArray.length === 0) return;
- 
-      const newJobs: UploadJob[] = fileArray.map((file) => ({
-        file,
-        progress: 'uploading' as const,
-      }));
- 
-      setJobs((prev) => [...prev, ...newJobs]);
- 
-      for (let i = 0; i < fileArray.length; i++) {
-        const file = fileArray[i];
-        const jobIndex = jobs.length + i;
- 
-        try {
-          const doc = await uploadDocument(courseId, file, accessToken);
- 
-          setJobs((prev) => {
-            const updated = [...prev];
-            Iif (updated[jobIndex]) updated[jobIndex] = { ...updated[jobIndex], progress: 'processing' };
-            return updated;
-          });
- 
-          await pollDocumentUntilTerminal(doc.id, accessToken);
- 
-          setJobs((prev) => {
-            const updated = [...prev];
-            Iif (updated[jobIndex]) updated[jobIndex] = { ...updated[jobIndex], progress: 'done' };
-            return updated;
-          });
- 
-          onUploadComplete?.();
-        } catch (err) {
-          const message = err instanceof Error ? err.message : 'Upload failed';
-          setJobs((prev) => {
-            const updated = [...prev];
-            Iif (updated[jobIndex])
-              updated[jobIndex] = { ...updated[jobIndex], progress: 'error', errorMessage: message };
-            return updated;
-          });
-          onUploadComplete?.();
-        }
-      }
-    },
-    [courseId, accessToken, jobs.length, onUploadComplete]
-  );
- 
-  const onDrop = useCallback(
-    (e: React.DragEvent) => {
-      e.preventDefault();
-      setIsDragOver(false);
-      Iif (e.dataTransfer.files.length > 0) {
-        handleFiles(e.dataTransfer.files);
-      }
-    },
-    [handleFiles]
-  );
- 
-  const activeJobs = jobs.filter((j) => j.progress === 'uploading' || j.progress === 'processing');
-  const errorJobs = jobs.filter((j) => j.progress === 'error');
- 
-  return (
-    <div>
-      <div
-        onDragOver={(e) => {
-          e.preventDefault();
-          setIsDragOver(true);
-        }}
-        onDragLeave={() => setIsDragOver(false)}
-        onDrop={onDrop}
-        onClick={() => inputRef.current?.click()}
-        className={`relative cursor-pointer rounded-lg border-2 border-dashed p-6 text-center transition-colors ${
-          isDragOver
-            ? 'border-orange-400 bg-orange-50'
-            : 'border-gray-300 hover:border-gray-400 bg-gray-50'
-        }`}
-      >
-        <input
-          ref={inputRef}
-          type="file"
-          multiple
-          accept=".pdf,.pptx,.ppt,.doc,.docx,.txt,.md"
-          className="sr-only"
-          onChange={(e) => {
-            Iif (e.target.files) handleFiles(e.target.files);
-            e.target.value = '';
-          }}
-        />
-        <svg className="mx-auto h-8 w-8 text-gray-400" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
-          <path strokeLinecap="round" strokeLinejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5" />
-        </svg>
-        <p className="mt-2 text-sm text-gray-600">
-          <span className="font-medium text-orange-600">Click to upload</span> or drag and drop
-        </p>
-        <p className="mt-1 text-xs text-gray-400">PDF, PPTX, DOC, TXT, MD</p>
-      </div>
- 
-      {activeJobs.length > 0 && (
-        <div className="mt-3 space-y-2">
-          {activeJobs.map((job, i) => (
-            <div key={i} className="flex items-center gap-2 text-sm text-gray-600">
-              <svg className="h-4 w-4 animate-spin text-orange-500" fill="none" viewBox="0 0 24 24">
-                <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
-                <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
-              </svg>
-              <span className="truncate flex-1">{job.file.name}</span>
-              <span className="text-xs text-gray-400 capitalize">{job.progress}</span>
-            </div>
-          ))}
-        </div>
-      )}
- 
-      {errorJobs.length > 0 && (
-        <div className="mt-3 space-y-2">
-          {errorJobs.map((job, i) => (
-            <div key={i} className="flex items-center gap-2 rounded bg-red-50 px-3 py-2 text-sm">
-              <svg className="h-4 w-4 text-red-500 flex-shrink-0" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor">
-                <path strokeLinecap="round" strokeLinejoin="round" d="M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z" />
-              </svg>
-              <span className="truncate flex-1 text-red-700">{job.file.name}</span>
-              <span className="text-xs text-red-500">{job.errorMessage}</span>
-            </div>
-          ))}
-        </div>
-      )}
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/components/documents/index.html b/apps/web/coverage/lcov-report/src/components/documents/index.html deleted file mode 100644 index a0bba40..0000000 --- a/apps/web/coverage/lcov-report/src/components/documents/index.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - Code coverage report for src/components/documents - - - - - - - - - -
-
-

All files src/components/documents

-
- -
- 0% - Statements - 0/94 -
- - -
- 0% - Branches - 0/27 -
- - -
- 0% - Functions - 0/24 -
- - -
- 0% - Lines - 0/81 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
DocumentProcessingPanel.tsx -
-
0%0/200%0/100%0/50%0/19
DocumentRow.tsx -
-
0%0/170%0/30%0/30%0/14
DocumentUpload.tsx -
-
0%0/570%0/140%0/160%0/48
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/components/providers/AuthProvider.tsx.html b/apps/web/coverage/lcov-report/src/components/providers/AuthProvider.tsx.html deleted file mode 100644 index bc4cb6d..0000000 --- a/apps/web/coverage/lcov-report/src/components/providers/AuthProvider.tsx.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - Code coverage report for src/components/providers/AuthProvider.tsx - - - - - - - - - -
-
-

All files / src/components/providers AuthProvider.tsx

-
- -
- 0% - Statements - 0/4 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/3 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-/**
- * Session provider wrapper for NextAuth.js
- * Wraps the application with the SessionProvider to enable authentication
- */
-import { SessionProvider } from 'next-auth/react';
-import { ReactNode } from 'react';
- 
-interface AuthProviderProps {
-  children: ReactNode;
-}
- 
-/**
- * Authentication provider component
- * Wraps children with NextAuth SessionProvider
- */
-export function AuthProvider({ children }: AuthProviderProps) {
-  return <SessionProvider>{children}</SessionProvider>;
-}
- 
-export default AuthProvider;
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/components/providers/index.html b/apps/web/coverage/lcov-report/src/components/providers/index.html deleted file mode 100644 index 7a659c4..0000000 --- a/apps/web/coverage/lcov-report/src/components/providers/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for src/components/providers - - - - - - - - - -
-
-

All files src/components/providers

-
- -
- 0% - Statements - 0/4 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/3 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
AuthProvider.tsx -
-
0%0/4100%0/00%0/10%0/3
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/components/study/OutputPane.tsx.html b/apps/web/coverage/lcov-report/src/components/study/OutputPane.tsx.html deleted file mode 100644 index 7434b2f..0000000 --- a/apps/web/coverage/lcov-report/src/components/study/OutputPane.tsx.html +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - Code coverage report for src/components/study/OutputPane.tsx - - - - - - - - - -
-
-

All files / src/components/study OutputPane.tsx

-
- -
- 0% - Statements - 0/1 -
- - -
- 100% - Branches - 0/0 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-export function OutputPane() {
-  return (
-    <div className="h-full flex flex-col">
-      <div className="flex-shrink-0 px-6 py-4 border-b border-gray-200 bg-white">
-        <h2 className="text-sm font-semibold text-gray-900 uppercase tracking-wide">
-          Explanation
-        </h2>
-      </div>
- 
-      <div className="flex-1 flex items-center justify-center p-8 bg-white">
-        <div className="text-center max-w-sm">
-          <svg
-            className="mx-auto h-12 w-12 text-gray-300"
-            fill="none"
-            viewBox="0 0 24 24"
-            strokeWidth={1}
-            stroke="currentColor"
-          >
-            <path
-              strokeLinecap="round"
-              strokeLinejoin="round"
-              d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.455 2.456L21.75 6l-1.036.259a3.375 3.375 0 00-2.455 2.456zM16.894 20.567L16.5 21.75l-.394-1.183a2.25 2.25 0 00-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 001.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 001.423 1.423l1.183.394-1.183.394a2.25 2.25 0 00-1.423 1.423z"
-            />
-          </svg>
-          <h3 className="mt-4 text-sm font-medium text-gray-900">
-            No explanation generated
-          </h3>
-          <p className="mt-1 text-sm text-gray-500">
-            Once a document is selected and processed, the reconstructed explanation
-            will appear here with source-grounded references.
-          </p>
-        </div>
-      </div>
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/components/study/SourcePane.tsx.html b/apps/web/coverage/lcov-report/src/components/study/SourcePane.tsx.html deleted file mode 100644 index dcf0669..0000000 --- a/apps/web/coverage/lcov-report/src/components/study/SourcePane.tsx.html +++ /dev/null @@ -1,220 +0,0 @@ - - - - - - Code coverage report for src/components/study/SourcePane.tsx - - - - - - - - - -
-
-

All files / src/components/study SourcePane.tsx

-
- -
- 0% - Statements - 0/1 -
- - -
- 0% - Branches - 0/1 -
- - -
- 0% - Functions - 0/1 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-interface SourcePaneProps {
-  courseTitle?: string;
-}
- 
-export function SourcePane({ courseTitle }: SourcePaneProps) {
-  return (
-    <div className="h-full flex flex-col">
-      <div className="flex-shrink-0 px-6 py-4 border-b border-gray-200 bg-white">
-        <h2 className="text-sm font-semibold text-gray-900 uppercase tracking-wide">
-          Source Material
-        </h2>
-        {courseTitle && (
-          <p className="mt-0.5 text-xs text-gray-500">{courseTitle}</p>
-        )}
-      </div>
- 
-      <div className="flex-1 flex items-center justify-center p-8 bg-gray-50">
-        <div className="text-center max-w-sm">
-          <svg
-            className="mx-auto h-12 w-12 text-gray-300"
-            fill="none"
-            viewBox="0 0 24 24"
-            strokeWidth={1}
-            stroke="currentColor"
-          >
-            <path
-              strokeLinecap="round"
-              strokeLinejoin="round"
-              d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z"
-            />
-          </svg>
-          <h3 className="mt-4 text-sm font-medium text-gray-900">
-            No document selected
-          </h3>
-          <p className="mt-1 text-sm text-gray-500">
-            Select a document from the course workspace to view its contents here.
-            Citations and highlights will be synced with the explanation panel.
-          </p>
-        </div>
-      </div>
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/components/study/SplitPane.tsx.html b/apps/web/coverage/lcov-report/src/components/study/SplitPane.tsx.html deleted file mode 100644 index 6b3d7dc..0000000 --- a/apps/web/coverage/lcov-report/src/components/study/SplitPane.tsx.html +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - Code coverage report for src/components/study/SplitPane.tsx - - - - - - - - - -
-
-

All files / src/components/study SplitPane.tsx

-
- -
- 0% - Statements - 0/24 -
- - -
- 0% - Branches - 0/6 -
- - -
- 0% - Functions - 0/4 -
- - -
- 0% - Lines - 0/23 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
'use client';
- 
-import { useCallback, useRef, useState, type ReactNode } from 'react';
- 
-interface SplitPaneProps {
-  left: ReactNode;
-  right: ReactNode;
-  defaultLeftPercent?: number;
-  minLeftPercent?: number;
-  maxLeftPercent?: number;
-}
- 
-export function SplitPane({
-  left,
-  right,
-  defaultLeftPercent = 50,
-  minLeftPercent = 25,
-  maxLeftPercent = 75,
-}: SplitPaneProps) {
-  const [leftPercent, setLeftPercent] = useState(defaultLeftPercent);
-  const containerRef = useRef<HTMLDivElement>(null);
-  const dragging = useRef(false);
- 
-  const onMouseDown = useCallback(
-    (e: React.MouseEvent) => {
-      e.preventDefault();
-      dragging.current = true;
- 
-      const onMouseMove = (ev: MouseEvent) => {
-        Iif (!dragging.current || !containerRef.current) return;
-        const rect = containerRef.current.getBoundingClientRect();
-        const percent = ((ev.clientX - rect.left) / rect.width) * 100;
-        setLeftPercent(Math.min(maxLeftPercent, Math.max(minLeftPercent, percent)));
-      };
- 
-      const onMouseUp = () => {
-        dragging.current = false;
-        document.removeEventListener('mousemove', onMouseMove);
-        document.removeEventListener('mouseup', onMouseUp);
-        document.body.style.cursor = '';
-        document.body.style.userSelect = '';
-      };
- 
-      document.body.style.cursor = 'col-resize';
-      document.body.style.userSelect = 'none';
-      document.addEventListener('mousemove', onMouseMove);
-      document.addEventListener('mouseup', onMouseUp);
-    },
-    [minLeftPercent, maxLeftPercent]
-  );
- 
-  return (
-    <div ref={containerRef} className="flex h-full w-full overflow-hidden">
-      <div style={{ width: `${leftPercent}%` }} className="overflow-auto">
-        {left}
-      </div>
- 
-      <div
-        onMouseDown={onMouseDown}
-        className="flex-shrink-0 w-1.5 cursor-col-resize bg-gray-200 hover:bg-orange-300 active:bg-orange-400 transition-colors relative group"
-      >
-        <div className="absolute inset-y-0 -left-1 -right-1" />
-        <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 h-8 w-1 rounded-full bg-gray-400 group-hover:bg-orange-500 transition-colors" />
-      </div>
- 
-      <div style={{ width: `${100 - leftPercent}%` }} className="overflow-auto">
-        {right}
-      </div>
-    </div>
-  );
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/components/study/index.html b/apps/web/coverage/lcov-report/src/components/study/index.html deleted file mode 100644 index 5a28792..0000000 --- a/apps/web/coverage/lcov-report/src/components/study/index.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - Code coverage report for src/components/study - - - - - - - - - -
-
-

All files src/components/study

-
- -
- 0% - Statements - 0/26 -
- - -
- 0% - Branches - 0/7 -
- - -
- 0% - Functions - 0/6 -
- - -
- 0% - Lines - 0/25 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
OutputPane.tsx -
-
0%0/1100%0/00%0/10%0/1
SourcePane.tsx -
-
0%0/10%0/10%0/10%0/1
SplitPane.tsx -
-
0%0/240%0/60%0/40%0/23
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/index.html b/apps/web/coverage/lcov-report/src/index.html deleted file mode 100644 index 05dd18f..0000000 --- a/apps/web/coverage/lcov-report/src/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for src - - - - - - - - - -
-
-

All files src

-
- -
- 0% - Statements - 0/3 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
middleware.ts -
-
0%0/3100%0/0100%0/00%0/1
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/lib/api.ts.html b/apps/web/coverage/lcov-report/src/lib/api.ts.html deleted file mode 100644 index dd1d53d..0000000 --- a/apps/web/coverage/lcov-report/src/lib/api.ts.html +++ /dev/null @@ -1,265 +0,0 @@ - - - - - - Code coverage report for src/lib/api.ts - - - - - - - - - -
-
-

All files / src/lib api.ts

-
- -
- 0% - Statements - 0/20 -
- - -
- 0% - Branches - 0/17 -
- - -
- 0% - Functions - 0/4 -
- - -
- 0% - Lines - 0/19 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
const API_BASE_URL =
-  process.env.NEXT_PUBLIC_API_BASE_URL ||
-  (process.env.NEXT_PUBLIC_API_URL
-    ? `${process.env.NEXT_PUBLIC_API_URL}/api`
-    : 'http://localhost:8000/api');
- 
-export class ApiError extends Error {
-  constructor(
-    public status: number,
-    message: string,
-    public details?: Record<string, unknown>
-  ) {
-    super(message);
-    this.name = 'ApiError';
-  }
-}
- 
-interface FetchOptions extends Omit<RequestInit, 'body'> {
-  body?: unknown;
-  accessToken?: string;
-}
- 
-async function handleResponse<T>(response: Response): Promise<T> {
-  Iif (!response.ok) {
-    const errorBody = await response.json().catch(() => ({}));
-    throw new ApiError(
-      response.status,
-      errorBody.detail || errorBody.message || `Request failed (${response.status})`,
-      errorBody
-    );
-  }
-  return response.json();
-}
- 
-export async function apiFetch<T>(
-  endpoint: string,
-  options: FetchOptions = {}
-): Promise<T> {
-  const { body, accessToken, headers: customHeaders, ...rest } = options;
- 
-  const headers: Record<string, string> = {
-    ...(customHeaders as Record<string, string>),
-  };
- 
-  Iif (accessToken) {
-    headers['Authorization'] = `Bearer ${accessToken}`;
-  }
- 
-  Iif (body !== undefined && !(body instanceof FormData)) {
-    headers['Content-Type'] = 'application/json';
-  }
- 
-  const response = await fetch(`${API_BASE_URL}${endpoint}`, {
-    ...rest,
-    headers,
-    body: body instanceof FormData ? body : body !== undefined ? JSON.stringify(body) : undefined,
-  });
- 
-  return handleResponse<T>(response);
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/lib/api/adapters.ts.html b/apps/web/coverage/lcov-report/src/lib/api/adapters.ts.html deleted file mode 100644 index e7d1467..0000000 --- a/apps/web/coverage/lcov-report/src/lib/api/adapters.ts.html +++ /dev/null @@ -1,328 +0,0 @@ - - - - - - Code coverage report for src/lib/api/adapters.ts - - - - - - - - - -
-
-

All files / src/lib/api adapters.ts

-
- -
- 0% - Statements - 0/26 -
- - -
- 0% - Branches - 0/9 -
- - -
- 0% - Functions - 0/4 -
- - -
- 0% - Lines - 0/21 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import type {
-  ApiDocumentListItem,
-  ApiDocumentDetail,
-  ApiDocumentPreview,
-  DocumentListRow,
-  DocumentDetailView,
-  DocumentPreviewView,
-  DocumentStatus,
-  ProcessingStage,
-} from './types';
- 
-function mimeToLabel(mime: string | null, filename: string): string {
-  Iif (mime) {
-    const sub = mime.split('/')[1];
-    Iif (sub === 'pdf') return 'PDF';
-    Iif (sub === 'vnd.openxmlformats-officedocument.presentationml.presentation') return 'PPTX';
-    Iif (sub === 'vnd.openxmlformats-officedocument.wordprocessingml.document') return 'DOCX';
-    Iif (sub === 'plain') return 'TXT';
-    Iif (sub) return sub.toUpperCase();
-  }
-  const ext = filename.split('.').pop()?.toUpperCase();
-  return ext || 'FILE';
-}
- 
-const TERMINAL_STATUSES: ReadonlySet<DocumentStatus> = new Set(['ready', 'error']);
- 
-export function toDocumentListRow(item: ApiDocumentListItem): DocumentListRow {
-  return {
-    id: item.id,
-    courseId: item.course_id,
-    filename: item.filename,
-    fileType: mimeToLabel(item.mime_type, item.filename),
-    size: item.size,
-    status: item.status,
-    processingStage: item.processing_stage,
-    isTerminal: TERMINAL_STATUSES.has(item.status),
-    errorMessage: item.error_message,
-    createdAt: item.created_at,
-    updatedAt: item.updated_at,
-  };
-}
- 
-export function toDocumentDetailView(item: ApiDocumentDetail): DocumentDetailView {
-  let normalizedMetadata: Record<string, unknown> | null = null;
-  Iif (item.metadata_json) {
-    try {
-      normalizedMetadata = JSON.parse(item.metadata_json);
-    } catch {
-      normalizedMetadata = null;
-    }
-  }
- 
-  return {
-    id: item.id,
-    courseId: item.course_id,
-    filename: item.filename,
-    fileType: mimeToLabel(item.mime_type, item.filename),
-    size: item.size,
-    status: item.status,
-    processingStage: item.processing_stage,
-    errorMessage: item.error_message,
-    parserUsed: item.parser_used,
-    pageCount: item.page_count,
-    chunkCount: item.chunk_count,
-    indexingStatus: item.indexing_status,
-    normalizedMetadata,
-    createdAt: item.created_at,
-    updatedAt: item.updated_at,
-  };
-}
- 
-export function toDocumentPreviewView(item: ApiDocumentPreview): DocumentPreviewView {
-  return {
-    id: item.id,
-    filename: item.filename,
-    extractedTextPreview: item.extracted_text_preview,
-    pageCount: item.page_count,
-    sections: item.sections,
-    sampleChunks: item.sample_chunks,
-  };
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/lib/api/courses.ts.html b/apps/web/coverage/lcov-report/src/lib/api/courses.ts.html deleted file mode 100644 index d02d963..0000000 --- a/apps/web/coverage/lcov-report/src/lib/api/courses.ts.html +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - Code coverage report for src/lib/api/courses.ts - - - - - - - - - -
-
-

All files / src/lib/api courses.ts

-
- -
- 0% - Statements - 0/9 -
- - -
- 0% - Branches - 0/2 -
- - -
- 0% - Functions - 0/4 -
- - -
- 0% - Lines - 0/9 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import { apiFetch } from '@/lib/api';
-import type { ApiCourse, ApiLesson, CreateCourseRequest } from './types';
- 
-export async function fetchCourses(
-  skip = 0,
-  limit = 100,
-  accessToken?: string,
-): Promise<ApiCourse[]> {
-  return apiFetch<ApiCourse[]>(`/courses?skip=${skip}&limit=${limit}`, {
-    accessToken,
-  });
-}
- 
-export async function fetchCourse(
-  courseId: string,
-  accessToken?: string,
-): Promise<ApiCourse> {
-  return apiFetch<ApiCourse>(`/courses/${courseId}`, { accessToken });
-}
- 
-export async function fetchCourseLessons(
-  courseId: string,
-  accessToken?: string,
-): Promise<ApiLesson[]> {
-  return apiFetch<ApiLesson[]>(`/courses/${courseId}/lessons`, { accessToken });
-}
- 
-export async function createCourse(
-  data: CreateCourseRequest,
-  accessToken?: string,
-): Promise<ApiCourse> {
-  return apiFetch<ApiCourse>('/courses', {
-    method: 'POST',
-    body: data,
-    accessToken,
-  });
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/lib/api/documents.ts.html b/apps/web/coverage/lcov-report/src/lib/api/documents.ts.html deleted file mode 100644 index 4cf0622..0000000 --- a/apps/web/coverage/lcov-report/src/lib/api/documents.ts.html +++ /dev/null @@ -1,460 +0,0 @@ - - - - - - Code coverage report for src/lib/api/documents.ts - - - - - - - - - -
-
-

All files / src/lib/api documents.ts

-
- -
- 0% - Statements - 0/37 -
- - -
- 0% - Branches - 0/9 -
- - -
- 0% - Functions - 0/11 -
- - -
- 0% - Lines - 0/35 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import { apiFetch, ApiError } from '@/lib/api';
-import type {
-  ApiDocumentListItem,
-  ApiDocumentDetail,
-  ApiDocumentPreview,
-  ApiDocumentStatusResponse,
-  DocumentListRow,
-  DocumentDetailView,
-  DocumentPreviewView,
-} from './types';
-import { toDocumentListRow, toDocumentDetailView, toDocumentPreviewView } from './adapters';
- 
-// ── Raw API calls (wire types) ──────────────────────────────────────────
- 
-export async function fetchDocumentsList(
-  courseId: string,
-  accessToken?: string,
-): Promise<ApiDocumentListItem[]> {
-  return apiFetch<ApiDocumentListItem[]>(`/courses/${courseId}/documents`, {
-    accessToken,
-  });
-}
- 
-export async function fetchDocumentStatus(
-  documentId: string,
-  accessToken?: string,
-): Promise<ApiDocumentStatusResponse> {
-  return apiFetch<ApiDocumentStatusResponse>(`/documents/${documentId}/status`, {
-    accessToken,
-  });
-}
- 
-export async function fetchDocumentDetail(
-  documentId: string,
-  accessToken?: string,
-): Promise<ApiDocumentDetail> {
-  return apiFetch<ApiDocumentDetail>(`/documents/${documentId}`, {
-    accessToken,
-  });
-}
- 
-export async function fetchDocumentPreview(
-  documentId: string,
-  accessToken?: string,
-): Promise<ApiDocumentPreview> {
-  return apiFetch<ApiDocumentPreview>(`/documents/${documentId}/preview`, {
-    accessToken,
-  });
-}
- 
-export async function uploadDocument(
-  courseId: string,
-  file: File,
-  accessToken?: string,
-): Promise<ApiDocumentListItem> {
-  const formData = new FormData();
-  formData.append('file', file);
-  return apiFetch<ApiDocumentListItem>(`/courses/${courseId}/documents`, {
-    method: 'POST',
-    body: formData,
-    accessToken,
-  });
-}
- 
-export async function deleteDocument(
-  documentId: string,
-  accessToken?: string,
-): Promise<{ message: string }> {
-  return apiFetch<{ message: string }>(`/documents/${documentId}`, {
-    method: 'DELETE',
-    accessToken,
-  });
-}
- 
-// ── Adapted calls (UI types) ───────────────────────────────────────────
- 
-export async function getDocumentListRows(
-  courseId: string,
-  accessToken?: string,
-): Promise<DocumentListRow[]> {
-  const items = await fetchDocumentsList(courseId, accessToken);
-  return items.map(toDocumentListRow);
-}
- 
-export async function getDocumentDetailView(
-  documentId: string,
-  accessToken?: string,
-): Promise<DocumentDetailView> {
-  const item = await fetchDocumentDetail(documentId, accessToken);
-  return toDocumentDetailView(item);
-}
- 
-export async function getDocumentPreviewView(
-  documentId: string,
-  accessToken?: string,
-): Promise<DocumentPreviewView> {
-  const item = await fetchDocumentPreview(documentId, accessToken);
-  return toDocumentPreviewView(item);
-}
- 
-// ── Polling helper ──────────────────────────────────────────────────────
- 
-export async function pollDocumentUntilTerminal(
-  documentId: string,
-  accessToken?: string,
-  intervalMs = 3000,
-  maxAttempts = 60,
-): Promise<ApiDocumentStatusResponse> {
-  for (let i = 0; i < maxAttempts; i++) {
-    try {
-      const status = await fetchDocumentStatus(documentId, accessToken);
-      Iif (status.status === 'ready' || status.status === 'error') {
-        return status;
-      }
-    } catch (err) {
-      if (err instanceof ApiError && err.status >= 500) {
-        // transient — keep polling
-      } else {
-        throw err;
-      }
-    }
-    await new Promise((resolve) => setTimeout(resolve, intervalMs));
-  }
-  throw new Error('Document processing timed out');
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/lib/api/index.html b/apps/web/coverage/lcov-report/src/lib/api/index.html deleted file mode 100644 index 3457472..0000000 --- a/apps/web/coverage/lcov-report/src/lib/api/index.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - Code coverage report for src/lib/api - - - - - - - - - -
-
-

All files src/lib/api

-
- -
- 0% - Statements - 0/76 -
- - -
- 0% - Branches - 0/20 -
- - -
- 0% - Functions - 0/19 -
- - -
- 0% - Lines - 0/69 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
adapters.ts -
-
0%0/260%0/90%0/40%0/21
courses.ts -
-
0%0/90%0/20%0/40%0/9
documents.ts -
-
0%0/370%0/90%0/110%0/35
index.ts -
-
0%0/4100%0/0100%0/00%0/4
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/lib/api/index.ts.html b/apps/web/coverage/lcov-report/src/lib/api/index.ts.html deleted file mode 100644 index 2537286..0000000 --- a/apps/web/coverage/lcov-report/src/lib/api/index.ts.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - Code coverage report for src/lib/api/index.ts - - - - - - - - - -
-
-

All files / src/lib/api index.ts

-
- -
- 0% - Statements - 0/4 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 0% - Lines - 0/4 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5  -  -  -  - 
export * from './types';
-export * from './adapters';
-export * from './documents';
-export * from './courses';
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/lib/auth/config.ts.html b/apps/web/coverage/lcov-report/src/lib/auth/config.ts.html deleted file mode 100644 index ebd5e8d..0000000 --- a/apps/web/coverage/lcov-report/src/lib/auth/config.ts.html +++ /dev/null @@ -1,334 +0,0 @@ - - - - - - Code coverage report for src/lib/auth/config.ts - - - - - - - - - -
-
-

All files / src/lib/auth config.ts

-
- -
- 0% - Statements - 0/29 -
- - -
- 0% - Branches - 0/25 -
- - -
- 0% - Functions - 0/4 -
- - -
- 0% - Lines - 0/27 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import type { AuthOptions } from 'next-auth';
-import CredentialsProvider from 'next-auth/providers/credentials';
- 
-const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000';
- 
-export const authOptions: AuthOptions = {
-  providers: [
-    CredentialsProvider({
-      name: 'credentials',
-      credentials: {
-        email: { label: 'Email', type: 'email' },
-        password: { label: 'Password', type: 'password' },
-      },
-      async authorize(credentials) {
-        Iif (!credentials?.email || !credentials?.password) {
-          throw new Error('Email and password are required');
-        }
- 
-        try {
-          const res = await fetch(`${API_URL}/api/auth/login`, {
-            method: 'POST',
-            headers: { 'Content-Type': 'application/json' },
-            body: JSON.stringify({
-              email: credentials.email,
-              password: credentials.password,
-            }),
-          });
- 
-          Iif (!res.ok) {
-            const error = await res.json().catch(() => ({}));
-            throw new Error(error.detail || 'Invalid email or password');
-          }
- 
-          const data = await res.json();
- 
-          return {
-            id: data.user?.id || data.id,
-            email: data.user?.email || credentials.email,
-            name: data.user?.display_name || null,
-            accessToken: data.access_token || data.tokens?.access_token,
-            refreshToken: data.refresh_token || data.tokens?.refresh_token,
-            role: data.user?.role || 'student',
-            displayName: data.user?.display_name || null,
-          };
-        } catch (error) {
-          Iif (error instanceof Error) {
-            throw error;
-          }
-          throw new Error('Authentication failed');
-        }
-      },
-    }),
-  ],
-  callbacks: {
-    async jwt({ token, user }) {
-      Iif (user) {
-        token.accessToken = (user as any).accessToken;
-        token.refreshToken = (user as any).refreshToken;
-        token.role = (user as any).role;
-        token.displayName = (user as any).displayName;
-      }
-      return token;
-    },
-    async session({ session, token }) {
-      Iif (session.user) {
-        (session.user as any).id = token.sub;
-        (session.user as any).accessToken = token.accessToken;
-        (session.user as any).role = token.role;
-        (session.user as any).displayName = token.displayName;
-      }
-      return session;
-    },
-  },
-  pages: {
-    signIn: '/login',
-    error: '/login',
-  },
-  session: {
-    strategy: 'jwt',
-    maxAge: 24 * 60 * 60,
-  },
-  secret: process.env.NEXTAUTH_SECRET,
-};
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/lib/auth/index.html b/apps/web/coverage/lcov-report/src/lib/auth/index.html deleted file mode 100644 index 4c07033..0000000 --- a/apps/web/coverage/lcov-report/src/lib/auth/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for src/lib/auth - - - - - - - - - -
-
-

All files src/lib/auth

-
- -
- 0% - Statements - 0/29 -
- - -
- 0% - Branches - 0/25 -
- - -
- 0% - Functions - 0/4 -
- - -
- 0% - Lines - 0/27 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
config.ts -
-
0%0/290%0/250%0/40%0/27
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/lib/index.html b/apps/web/coverage/lcov-report/src/lib/index.html deleted file mode 100644 index da6d77b..0000000 --- a/apps/web/coverage/lcov-report/src/lib/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for src/lib - - - - - - - - - -
-
-

All files src/lib

-
- -
- 0% - Statements - 0/20 -
- - -
- 0% - Branches - 0/17 -
- - -
- 0% - Functions - 0/4 -
- - -
- 0% - Lines - 0/19 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
api.ts -
-
0%0/200%0/170%0/40%0/19
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/lib/middleware/auth-guard.ts.html b/apps/web/coverage/lcov-report/src/lib/middleware/auth-guard.ts.html deleted file mode 100644 index 7a1bb34..0000000 --- a/apps/web/coverage/lcov-report/src/lib/middleware/auth-guard.ts.html +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - Code coverage report for src/lib/middleware/auth-guard.ts - - - - - - - - - -
-
-

All files / src/lib/middleware auth-guard.ts

-
- -
- 0% - Statements - 0/17 -
- - -
- 0% - Branches - 0/7 -
- - -
- 0% - Functions - 0/2 -
- - -
- 0% - Lines - 0/16 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import { NextResponse } from 'next/server';
-import { getToken } from 'next-auth/jwt';
-import type { NextRequest } from 'next/server';
- 
-const PUBLIC_PATHS = ['/login', '/signup', '/api/auth'];
- 
-export async function authMiddleware(request: NextRequest) {
-  const { pathname } = request.nextUrl;
- 
-  const isPublic = PUBLIC_PATHS.some(
-    (path) => pathname === path || pathname.startsWith(path + '/')
-  );
- 
-  Iif (isPublic || pathname.startsWith('/_next') || pathname.startsWith('/favicon')) {
-    return NextResponse.next();
-  }
- 
-  const token = await getToken({
-    req: request,
-    secret: process.env.NEXTAUTH_SECRET,
-  });
- 
-  Iif (!token) {
-    const loginUrl = new URL('/login', request.url);
-    loginUrl.searchParams.set('callbackUrl', pathname);
-    return NextResponse.redirect(loginUrl);
-  }
- 
-  return NextResponse.next();
-}
- 
-export const config = {
-  matcher: ['/((?!_next/static|_next/image|favicon.ico|public/).*)'],
-};
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/lib/middleware/index.html b/apps/web/coverage/lcov-report/src/lib/middleware/index.html deleted file mode 100644 index 6f7dde7..0000000 --- a/apps/web/coverage/lcov-report/src/lib/middleware/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - Code coverage report for src/lib/middleware - - - - - - - - - -
-
-

All files src/lib/middleware

-
- -
- 0% - Statements - 0/17 -
- - -
- 0% - Branches - 0/7 -
- - -
- 0% - Functions - 0/2 -
- - -
- 0% - Lines - 0/16 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
auth-guard.ts -
-
0%0/170%0/70%0/20%0/16
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/lib/services/courses.ts.html b/apps/web/coverage/lcov-report/src/lib/services/courses.ts.html deleted file mode 100644 index ffeba07..0000000 --- a/apps/web/coverage/lcov-report/src/lib/services/courses.ts.html +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - Code coverage report for src/lib/services/courses.ts - - - - - - - - - -
-
-

All files / src/lib/services courses.ts

-
- -
- 0% - Statements - 0/9 -
- - -
- 0% - Branches - 0/2 -
- - -
- 0% - Functions - 0/4 -
- - -
- 0% - Lines - 0/9 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import { apiFetch } from '@/lib/api';
- 
-export interface Course {
-  id: number;
-  title: string;
-  description?: string;
-}
- 
-export interface Lesson {
-  id: number;
-  title: string;
-  content?: string;
-}
- 
-export interface CourseWithLessons extends Course {
-  lessons: Lesson[];
-}
- 
-export async function getCourses(
-  skip = 0,
-  limit = 100,
-  accessToken?: string
-): Promise<Course[]> {
-  return apiFetch<Course[]>(`/courses?skip=${skip}&limit=${limit}`, {
-    accessToken,
-  });
-}
- 
-export async function getCourse(
-  courseId: string,
-  accessToken?: string
-): Promise<Course> {
-  return apiFetch<Course>(`/courses/${courseId}`, { accessToken });
-}
- 
-export async function getCourseLessons(
-  courseId: string,
-  accessToken?: string
-): Promise<Lesson[]> {
-  return apiFetch<Lesson[]>(`/courses/${courseId}/lessons`, { accessToken });
-}
- 
-export async function getLesson(
-  lessonId: string,
-  accessToken?: string
-): Promise<Lesson> {
-  return apiFetch<Lesson>(`/lessons/${lessonId}`, { accessToken });
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/lib/services/documents.ts.html b/apps/web/coverage/lcov-report/src/lib/services/documents.ts.html deleted file mode 100644 index ec5e8e3..0000000 --- a/apps/web/coverage/lcov-report/src/lib/services/documents.ts.html +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - Code coverage report for src/lib/services/documents.ts - - - - - - - - - -
-
-

All files / src/lib/services documents.ts

-
- -
- 0% - Statements - 0/23 -
- - -
- 0% - Branches - 0/9 -
- - -
- 0% - Functions - 0/6 -
- - -
- 0% - Lines - 0/21 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
import { apiFetch, ApiError } from '@/lib/api';
- 
-export type DocumentStatus = 'uploading' | 'processing' | 'ready' | 'error';
- 
-export interface CourseDocument {
-  id: string;
-  filename: string;
-  size: number;
-  status: DocumentStatus;
-  error_message?: string;
-  created_at: string;
-}
- 
-export interface DocumentStatusResponse {
-  id: string;
-  status: DocumentStatus;
-  progress?: number;
-  error_message?: string;
-}
- 
-export async function getDocuments(
-  courseId: string,
-  accessToken?: string
-): Promise<CourseDocument[]> {
-  return apiFetch<CourseDocument[]>(`/courses/${courseId}/documents`, {
-    accessToken,
-  });
-}
- 
-export async function uploadDocument(
-  courseId: string,
-  file: File,
-  accessToken?: string
-): Promise<CourseDocument> {
-  const formData = new FormData();
-  formData.append('file', file);
- 
-  return apiFetch<CourseDocument>(`/courses/${courseId}/documents`, {
-    method: 'POST',
-    body: formData,
-    accessToken,
-  });
-}
- 
-export async function getDocumentStatus(
-  documentId: string,
-  accessToken?: string
-): Promise<DocumentStatusResponse> {
-  return apiFetch<DocumentStatusResponse>(`/documents/${documentId}/status`, {
-    accessToken,
-  });
-}
- 
-export async function deleteDocument(
-  documentId: string,
-  accessToken?: string
-): Promise<{ message: string }> {
-  return apiFetch<{ message: string }>(`/documents/${documentId}`, {
-    method: 'DELETE',
-    accessToken,
-  });
-}
- 
-/**
- * Poll a document's status until it reaches a terminal state.
- * Returns the final status, or throws if polling times out.
- */
-export async function pollDocumentStatus(
-  documentId: string,
-  accessToken?: string,
-  intervalMs = 3000,
-  maxAttempts = 60
-): Promise<DocumentStatusResponse> {
-  for (let i = 0; i < maxAttempts; i++) {
-    try {
-      const status = await getDocumentStatus(documentId, accessToken);
-      Iif (status.status === 'ready' || status.status === 'error') {
-        return status;
-      }
-    } catch (err) {
-      if (err instanceof ApiError && err.status >= 500) {
-        // Server error — keep polling
-      } else {
-        throw err;
-      }
-    }
-    await new Promise((resolve) => setTimeout(resolve, intervalMs));
-  }
-  throw new Error('Document processing timed out');
-}
- 
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/lib/services/index.html b/apps/web/coverage/lcov-report/src/lib/services/index.html deleted file mode 100644 index d265b6c..0000000 --- a/apps/web/coverage/lcov-report/src/lib/services/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - Code coverage report for src/lib/services - - - - - - - - - -
-
-

All files src/lib/services

-
- -
- 0% - Statements - 0/32 -
- - -
- 0% - Branches - 0/11 -
- - -
- 0% - Functions - 0/10 -
- - -
- 0% - Lines - 0/30 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FileStatementsBranchesFunctionsLines
courses.ts -
-
0%0/90%0/20%0/40%0/9
documents.ts -
-
0%0/230%0/90%0/60%0/21
-
-
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov-report/src/middleware.ts.html b/apps/web/coverage/lcov-report/src/middleware.ts.html deleted file mode 100644 index 373b3ee..0000000 --- a/apps/web/coverage/lcov-report/src/middleware.ts.html +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - Code coverage report for src/middleware.ts - - - - - - - - - -
-
-

All files / src middleware.ts

-
- -
- 0% - Statements - 0/3 -
- - -
- 100% - Branches - 0/0 -
- - -
- 100% - Functions - 0/0 -
- - -
- 0% - Lines - 0/1 -
- - -
-

- Press n or j to go to the next uncovered block, b, p or k for the previous block. -

- -
-
-

-
1 -2 -3 -4 -5 -6  -  -  -  -  - 
/**
- * Next.js Middleware
- * Handles authentication routing and protection
- */
-export { authMiddleware as default, config } from '@/lib/middleware/auth-guard';
- -
-
- - - - - - - - \ No newline at end of file diff --git a/apps/web/coverage/lcov.info b/apps/web/coverage/lcov.info deleted file mode 100644 index ced756e..0000000 --- a/apps/web/coverage/lcov.info +++ /dev/null @@ -1,1471 +0,0 @@ -TN: -SF:src/middleware.ts -FNF:0 -FNH:0 -DA:5,0 -LF:1 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/app/layout.tsx -FN:11,RootLayout -FNF:1 -FNH:0 -FNDA:0,RootLayout -DA:2,0 -DA:3,0 -DA:5,0 -DA:11,0 -LF:4 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/app/page.tsx -FN:7,Home -FN:11,(anonymous_2) -FNF:2 -FNH:0 -FNDA:0,Home -FNDA:0,(anonymous_2) -DA:3,0 -DA:4,0 -DA:5,0 -DA:7,0 -DA:8,0 -DA:9,0 -DA:11,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -DA:19,0 -DA:29,0 -LF:13 -LH:0 -BRDA:12,0,0,0 -BRDA:12,0,1,0 -BRDA:14,1,0,0 -BRDA:19,2,0,0 -BRDA:19,3,0,0 -BRDA:19,3,1,0 -BRF:6 -BRH:0 -end_of_record -TN: -SF:src/app/(auth)/layout.tsx -FN:11,AuthLayout -FNF:1 -FNH:0 -FNDA:0,AuthLayout -DA:11,0 -LF:1 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/app/(auth)/login/page.tsx -FN:18,LoginPage -FN:36,(anonymous_3) -FN:58,(anonymous_4) -FN:124,(anonymous_5) -FN:153,(anonymous_6) -FNF:5 -FNH:5 -FNDA:327,LoginPage -FNDA:15,(anonymous_3) -FNDA:15,(anonymous_4) -FNDA:179,(anonymous_5) -FNDA:106,(anonymous_6) -DA:7,2 -DA:8,2 -DA:9,2 -DA:10,2 -DA:18,2 -DA:19,327 -DA:20,327 -DA:21,327 -DA:22,327 -DA:24,327 -DA:25,325 -DA:26,325 -DA:27,325 -DA:31,325 -DA:36,325 -DA:37,15 -DA:40,15 -DA:41,3 -DA:42,12 -DA:43,2 -DA:47,15 -DA:48,6 -DA:51,15 -DA:52,15 -DA:58,325 -DA:59,15 -DA:62,15 -DA:65,15 -DA:66,6 -DA:69,9 -DA:71,9 -DA:72,9 -DA:79,8 -DA:80,2 -DA:81,6 -DA:82,6 -DA:83,6 -DA:86,0 -DA:88,8 -DA:124,179 -DA:153,106 -LF:41 -LH:40 -BRDA:21,0,0,327 -BRDA:21,0,1,262 -BRDA:31,1,0,36 -BRDA:31,1,1,289 -BRDA:40,2,0,3 -BRDA:40,2,1,12 -BRDA:42,3,0,2 -BRDA:47,4,0,6 -BRDA:65,5,0,6 -BRDA:79,6,0,2 -BRDA:79,6,1,6 -BRDA:81,7,0,6 -BRDA:97,8,0,325 -BRDA:104,9,0,325 -BRDA:126,10,0,6 -BRDA:126,10,1,319 -BRDA:129,11,0,6 -BRDA:129,11,1,319 -BRDA:130,12,0,6 -BRDA:130,12,1,319 -BRDA:133,13,0,325 -BRDA:155,14,0,7 -BRDA:155,14,1,318 -BRDA:158,15,0,7 -BRDA:158,15,1,318 -BRDA:159,16,0,7 -BRDA:159,16,1,318 -BRDA:162,17,0,325 -BRDA:176,18,0,9 -BRDA:176,18,1,316 -BRF:30 -BRH:30 -end_of_record -TN: -SF:src/app/(auth)/signup/page.tsx -FN:23,SignupPage -FN:36,(anonymous_3) -FN:78,(anonymous_4) -FN:164,(anonymous_5) -FN:193,(anonymous_6) -FN:222,(anonymous_7) -FN:255,(anonymous_8) -FNF:7 -FNH:7 -FNDA:774,SignupPage -FNDA:18,(anonymous_3) -FNDA:18,(anonymous_4) -FNDA:17,(anonymous_5) -FNDA:281,(anonymous_6) -FNDA:217,(anonymous_7) -FNDA:209,(anonymous_8) -DA:7,2 -DA:8,2 -DA:9,2 -DA:10,2 -DA:13,2 -DA:23,2 -DA:24,774 -DA:26,774 -DA:27,772 -DA:28,772 -DA:29,772 -DA:30,772 -DA:31,772 -DA:36,772 -DA:37,18 -DA:40,18 -DA:41,1 -DA:42,17 -DA:43,1 -DA:47,18 -DA:48,0 -DA:49,18 -DA:50,1 -DA:51,17 -DA:52,1 -DA:53,16 -DA:54,1 -DA:55,15 -DA:56,1 -DA:60,18 -DA:61,1 -DA:62,17 -DA:63,1 -DA:67,18 -DA:68,0 -DA:71,18 -DA:72,18 -DA:78,772 -DA:79,18 -DA:82,18 -DA:85,18 -DA:86,8 -DA:89,10 -DA:91,10 -DA:93,10 -DA:105,8 -DA:106,3 -DA:108,3 -DA:109,2 -DA:110,1 -DA:111,0 -DA:113,1 -DA:115,3 -DA:119,5 -DA:126,5 -DA:128,0 -DA:129,5 -DA:130,5 -DA:131,5 -DA:134,1 -DA:136,9 -DA:164,17 -DA:193,281 -DA:222,217 -DA:255,209 -LF:65 -LH:61 -BRDA:13,0,0,2 -BRDA:13,0,1,2 -BRDA:40,1,0,1 -BRDA:40,1,1,17 -BRDA:42,2,0,1 -BRDA:47,3,0,0 -BRDA:47,3,1,18 -BRDA:49,4,0,1 -BRDA:49,4,1,17 -BRDA:51,5,0,1 -BRDA:51,5,1,16 -BRDA:53,6,0,1 -BRDA:53,6,1,15 -BRDA:55,7,0,1 -BRDA:60,8,0,1 -BRDA:60,8,1,17 -BRDA:62,9,0,1 -BRDA:67,10,0,0 -BRDA:67,11,0,18 -BRDA:67,11,1,2 -BRDA:85,12,0,8 -BRDA:101,13,0,10 -BRDA:101,13,1,8 -BRDA:105,14,0,3 -BRDA:108,15,0,2 -BRDA:108,15,1,1 -BRDA:110,16,0,0 -BRDA:110,16,1,1 -BRDA:111,17,0,0 -BRDA:111,17,1,0 -BRDA:113,18,0,1 -BRDA:113,18,1,0 -BRDA:126,19,0,0 -BRDA:126,19,1,5 -BRDA:129,20,0,5 -BRDA:145,21,0,772 -BRDA:166,22,0,0 -BRDA:166,22,1,772 -BRDA:169,23,0,0 -BRDA:169,23,1,772 -BRDA:170,24,0,0 -BRDA:170,24,1,772 -BRDA:173,25,0,772 -BRDA:195,26,0,4 -BRDA:195,26,1,768 -BRDA:198,27,0,4 -BRDA:198,27,1,768 -BRDA:199,28,0,4 -BRDA:199,28,1,768 -BRDA:202,29,0,772 -BRDA:224,30,0,4 -BRDA:224,30,1,768 -BRDA:227,31,0,4 -BRDA:227,31,1,768 -BRDA:228,32,0,4 -BRDA:228,32,1,768 -BRDA:232,33,0,4 -BRDA:257,34,0,2 -BRDA:257,34,1,770 -BRDA:260,35,0,2 -BRDA:260,35,1,770 -BRDA:261,36,0,2 -BRDA:261,36,1,770 -BRDA:264,37,0,772 -BRDA:278,38,0,10 -BRDA:278,38,1,762 -BRF:66 -BRH:56 -end_of_record -TN: -SF:src/app/api/auth/[...nextauth]/route.ts -FNF:0 -FNH:0 -DA:4,0 -DA:5,0 -DA:7,0 -DA:9,0 -LF:4 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/app/courses/page.tsx -FN:10,CoursesPage -FN:17,(anonymous_3) -FN:24,fetchCourses -FN:48,(anonymous_5) -FN:80,(anonymous_6) -FN:96,(anonymous_7) -FNF:6 -FNH:0 -FNDA:0,CoursesPage -FNDA:0,(anonymous_3) -FNDA:0,fetchCourses -FNDA:0,(anonymous_5) -FNDA:0,(anonymous_6) -FNDA:0,(anonymous_7) -DA:3,0 -DA:4,0 -DA:5,0 -DA:6,0 -DA:7,0 -DA:8,0 -DA:10,0 -DA:11,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -DA:17,0 -DA:18,0 -DA:19,0 -DA:20,0 -DA:22,0 -DA:25,0 -DA:26,0 -DA:27,0 -DA:29,0 -DA:31,0 -DA:35,0 -DA:38,0 -DA:49,0 -DA:80,0 -DA:97,0 -LF:27 -LH:0 -BRDA:18,0,0,0 -BRDA:22,1,0,0 -BRDA:29,2,0,0 -BRDA:29,2,1,0 -BRDA:38,3,0,0 -BRDA:38,4,0,0 -BRDA:38,4,1,0 -BRDA:38,4,2,0 -BRDA:77,5,0,0 -BRDA:87,6,0,0 -BRF:10 -BRH:0 -end_of_record -TN: -SF:src/app/courses/[courseId]/layout.tsx -FN:11,CourseLayout -FN:21,isActive -FN:43,(anonymous_4) -FNF:3 -FNH:0 -FNDA:0,CourseLayout -FNDA:0,isActive -FNDA:0,(anonymous_4) -DA:3,0 -DA:4,0 -DA:11,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:16,0 -DA:22,0 -DA:44,0 -LF:9 -LH:0 -BRDA:22,0,0,0 -BRDA:22,0,1,0 -BRDA:48,1,0,0 -BRDA:48,1,1,0 -BRF:4 -BRH:0 -end_of_record -TN: -SF:src/app/courses/[courseId]/page.tsx -FN:10,CourseWorkspacePage -FN:23,(anonymous_2) -FN:24,(anonymous_3) -FN:27,handleViewPreview -FN:31,(anonymous_5) -FN:32,load -FN:59,(anonymous_7) -FN:79,(anonymous_8) -FN:115,(anonymous_9) -FNF:9 -FNH:0 -FNDA:0,CourseWorkspacePage -FNDA:0,(anonymous_2) -FNDA:0,(anonymous_3) -FNDA:0,handleViewPreview -FNDA:0,(anonymous_5) -FNDA:0,load -FNDA:0,(anonymous_7) -FNDA:0,(anonymous_8) -FNDA:0,(anonymous_9) -DA:3,0 -DA:4,0 -DA:5,0 -DA:6,0 -DA:7,0 -DA:8,0 -DA:10,0 -DA:11,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -DA:17,0 -DA:18,0 -DA:19,0 -DA:20,0 -DA:21,0 -DA:23,0 -DA:24,0 -DA:28,0 -DA:31,0 -DA:33,0 -DA:34,0 -DA:38,0 -DA:39,0 -DA:41,0 -DA:43,0 -DA:47,0 -DA:50,0 -DA:60,0 -DA:73,0 -DA:79,0 -DA:116,0 -LF:33 -LH:0 -BRDA:41,0,0,0 -BRDA:41,0,1,0 -BRDA:47,1,0,0 -BRDA:50,2,0,0 -BRDA:73,3,0,0 -BRDA:73,4,0,0 -BRDA:73,4,1,0 -BRDA:77,5,0,0 -BRDA:77,5,1,0 -BRDA:93,6,0,0 -BRDA:107,7,0,0 -BRF:11 -BRH:0 -end_of_record -TN: -SF:src/app/courses/[courseId]/documents/[documentId]/preview/page.tsx -FN:9,DocumentPreviewPage -FN:21,(anonymous_2) -FN:33,(anonymous_3) -FN:62,(anonymous_4) -FN:78,(anonymous_5) -FN:119,(anonymous_6) -FN:142,(anonymous_7) -FNF:7 -FNH:0 -FNDA:0,DocumentPreviewPage -FNDA:0,(anonymous_2) -FNDA:0,(anonymous_3) -FNDA:0,(anonymous_4) -FNDA:0,(anonymous_5) -FNDA:0,(anonymous_6) -FNDA:0,(anonymous_7) -DA:3,0 -DA:4,0 -DA:5,0 -DA:6,0 -DA:9,0 -DA:10,0 -DA:11,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -DA:17,0 -DA:18,0 -DA:19,0 -DA:21,0 -DA:22,0 -DA:23,0 -DA:24,0 -DA:25,0 -DA:27,0 -DA:29,0 -DA:33,0 -DA:34,0 -DA:37,0 -DA:49,0 -DA:62,0 -DA:78,0 -DA:120,0 -DA:143,0 -LF:29 -LH:0 -BRDA:27,0,0,0 -BRDA:27,0,1,0 -BRDA:37,1,0,0 -BRDA:49,2,0,0 -BRDA:49,3,0,0 -BRDA:49,3,1,0 -BRDA:53,4,0,0 -BRDA:53,4,1,0 -BRDA:88,5,0,0 -BRDA:89,6,0,0 -BRDA:89,6,1,0 -BRDA:102,7,0,0 -BRDA:118,8,0,0 -BRDA:117,9,0,0 -BRDA:117,9,1,0 -BRDA:141,10,0,0 -BRDA:140,11,0,0 -BRDA:140,11,1,0 -BRDA:146,12,0,0 -BRDA:146,12,1,0 -BRF:20 -BRH:0 -end_of_record -TN: -SF:src/app/courses/[courseId]/study/page.tsx -FN:11,StudyPage -FN:20,(anonymous_2) -FN:21,load -FNF:3 -FNH:0 -FNDA:0,StudyPage -FNDA:0,(anonymous_2) -FNDA:0,load -DA:3,0 -DA:4,0 -DA:5,0 -DA:6,0 -DA:7,0 -DA:8,0 -DA:9,0 -DA:11,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -DA:17,0 -DA:18,0 -DA:20,0 -DA:22,0 -DA:23,0 -DA:24,0 -DA:28,0 -DA:31,0 -DA:34,0 -LF:21 -LH:0 -BRDA:31,0,0,0 -BRDA:34,1,0,0 -BRF:2 -BRH:0 -end_of_record -TN: -SF:src/app/dashboard/page.tsx -FN:9,DashboardPage -FN:15,(anonymous_3) -FN:18,fetchCourses -FN:48,(anonymous_5) -FNF:4 -FNH:0 -FNDA:0,DashboardPage -FNDA:0,(anonymous_3) -FNDA:0,fetchCourses -FNDA:0,(anonymous_5) -DA:3,0 -DA:4,0 -DA:5,0 -DA:6,0 -DA:7,0 -DA:9,0 -DA:10,0 -DA:11,0 -DA:12,0 -DA:13,0 -DA:15,0 -DA:16,0 -DA:19,0 -DA:20,0 -DA:21,0 -DA:25,0 -DA:29,0 -DA:32,0 -DA:43,0 -DA:44,0 -DA:45,0 -DA:48,0 -DA:49,0 -LF:23 -LH:0 -BRDA:16,0,0,0 -BRDA:32,1,0,0 -BRDA:43,2,0,0 -BRDA:72,3,0,0 -BRDA:72,3,1,0 -BRDA:87,4,0,0 -BRDA:87,4,1,0 -BRDA:93,5,0,0 -BRDA:93,5,1,0 -BRDA:106,6,0,0 -BRDA:106,6,1,0 -BRF:11 -BRH:0 -end_of_record -TN: -SF:src/components/courses/CourseCard.tsx -FN:10,CourseCard -FNF:1 -FNH:0 -FNDA:0,CourseCard -DA:3,0 -DA:10,0 -LF:2 -LH:0 -BRDA:22,0,0,0 -BRF:1 -BRH:0 -end_of_record -TN: -SF:src/components/courses/DocumentList.tsx -FN:18,formatFileSize -FN:24,formatTime -FN:37,DocumentList -FN:51,(anonymous_4) -FN:72,(anonymous_5) -FN:76,(anonymous_6) -FN:77,(anonymous_7) -FN:79,(anonymous_8) -FN:81,(anonymous_9) -FN:86,handleRefresh -FN:91,toggleExpand -FN:92,(anonymous_12) -FN:98,(anonymous_13) -FN:116,(anonymous_14) -FN:177,(anonymous_15) -FN:183,(anonymous_16) -FNF:16 -FNH:0 -FNDA:0,formatFileSize -FNDA:0,formatTime -FNDA:0,DocumentList -FNDA:0,(anonymous_4) -FNDA:0,(anonymous_5) -FNDA:0,(anonymous_6) -FNDA:0,(anonymous_7) -FNDA:0,(anonymous_8) -FNDA:0,(anonymous_9) -FNDA:0,handleRefresh -FNDA:0,toggleExpand -FNDA:0,(anonymous_12) -FNDA:0,(anonymous_13) -FNDA:0,(anonymous_14) -FNDA:0,(anonymous_15) -FNDA:0,(anonymous_16) -DA:3,0 -DA:4,0 -DA:6,0 -DA:7,0 -DA:16,0 -DA:19,0 -DA:20,0 -DA:21,0 -DA:25,0 -DA:26,0 -DA:33,0 -DA:37,0 -DA:43,0 -DA:44,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:48,0 -DA:50,0 -DA:52,0 -DA:53,0 -DA:54,0 -DA:55,0 -DA:57,0 -DA:58,0 -DA:59,0 -DA:60,0 -DA:61,0 -DA:62,0 -DA:65,0 -DA:66,0 -DA:72,0 -DA:73,0 -DA:76,0 -DA:77,0 -DA:78,0 -DA:79,0 -DA:81,0 -DA:82,0 -DA:87,0 -DA:88,0 -DA:92,0 -DA:95,0 -DA:99,0 -DA:111,0 -DA:116,0 -DA:125,0 -DA:178,0 -DA:179,0 -DA:183,0 -LF:50 -LH:0 -BRDA:19,0,0,0 -BRDA:20,1,0,0 -BRDA:40,2,0,0 -BRDA:51,3,0,0 -BRDA:53,4,0,0 -BRDA:57,5,0,0 -BRDA:57,5,1,0 -BRDA:58,6,0,0 -BRDA:58,6,1,0 -BRDA:58,7,0,0 -BRDA:58,7,1,0 -BRDA:61,8,0,0 -BRDA:78,9,0,0 -BRDA:82,10,0,0 -BRDA:92,11,0,0 -BRDA:92,11,1,0 -BRDA:95,12,0,0 -BRDA:111,13,0,0 -BRDA:125,14,0,0 -BRDA:151,15,0,0 -BRDA:151,15,1,0 -BRDA:160,16,0,0 -BRDA:160,16,1,0 -BRDA:172,17,0,0 -BRDA:172,17,1,0 -BRDA:190,18,0,0 -BRDA:190,18,1,0 -BRDA:216,19,0,0 -BRDA:216,19,1,0 -BRDA:226,20,0,0 -BRF:30 -BRH:0 -end_of_record -TN: -SF:src/components/courses/ProcessingIndicator.tsx -FN:49,ProcessingIndicator -FNF:1 -FNH:0 -FNDA:0,ProcessingIndicator -DA:11,0 -DA:38,0 -DA:49,0 -DA:50,0 -DA:51,0 -LF:5 -LH:0 -BRDA:49,0,0,0 -BRDA:51,1,0,0 -BRDA:51,1,1,0 -BRDA:51,2,0,0 -BRDA:51,2,1,0 -BRDA:51,2,2,0 -BRDA:59,3,0,0 -BRDA:59,3,1,0 -BRF:8 -BRH:0 -end_of_record -TN: -SF:src/components/documents/DocumentProcessingPanel.tsx -FN:13,DetailRow -FN:22,DocumentProcessingPanel -FN:31,(anonymous_3) -FN:43,(anonymous_4) -FN:97,(anonymous_5) -FNF:5 -FNH:0 -FNDA:0,DetailRow -FNDA:0,DocumentProcessingPanel -FNDA:0,(anonymous_3) -FNDA:0,(anonymous_4) -FNDA:0,(anonymous_5) -DA:3,0 -DA:4,0 -DA:22,0 -DA:27,0 -DA:28,0 -DA:29,0 -DA:31,0 -DA:32,0 -DA:33,0 -DA:34,0 -DA:35,0 -DA:37,0 -DA:39,0 -DA:43,0 -DA:44,0 -DA:47,0 -DA:57,0 -DA:68,0 -DA:97,0 -LF:19 -LH:0 -BRDA:17,0,0,0 -BRDA:37,1,0,0 -BRDA:37,1,1,0 -BRDA:47,2,0,0 -BRDA:57,3,0,0 -BRDA:68,4,0,0 -BRDA:79,5,0,0 -BRDA:85,6,0,0 -BRDA:95,7,0,0 -BRDA:95,7,1,0 -BRF:10 -BRH:0 -end_of_record -TN: -SF:src/components/documents/DocumentRow.tsx -FN:14,formatFileSize -FN:20,DocumentRow -FN:23,handleDelete -FNF:3 -FNH:0 -FNDA:0,formatFileSize -FNDA:0,DocumentRow -FNDA:0,handleDelete -DA:3,0 -DA:5,0 -DA:6,0 -DA:15,0 -DA:16,0 -DA:17,0 -DA:20,0 -DA:21,0 -DA:24,0 -DA:25,0 -DA:26,0 -DA:27,0 -DA:28,0 -DA:30,0 -LF:14 -LH:0 -BRDA:15,0,0,0 -BRDA:16,1,0,0 -BRDA:24,2,0,0 -BRF:3 -BRH:0 -end_of_record -TN: -SF:src/components/documents/DocumentUpload.tsx -FN:18,DocumentUpload -FN:24,(anonymous_2) -FN:28,(anonymous_3) -FN:33,(anonymous_4) -FN:42,(anonymous_5) -FN:50,(anonymous_6) -FN:59,(anonymous_7) -FN:73,(anonymous_8) -FN:83,(anonymous_9) -FN:84,(anonymous_10) -FN:89,(anonymous_11) -FN:93,(anonymous_12) -FN:95,(anonymous_13) -FN:108,(anonymous_14) -FN:124,(anonymous_15) -FN:139,(anonymous_16) -FNF:16 -FNH:0 -FNDA:0,DocumentUpload -FNDA:0,(anonymous_2) -FNDA:0,(anonymous_3) -FNDA:0,(anonymous_4) -FNDA:0,(anonymous_5) -FNDA:0,(anonymous_6) -FNDA:0,(anonymous_7) -FNDA:0,(anonymous_8) -FNDA:0,(anonymous_9) -FNDA:0,(anonymous_10) -FNDA:0,(anonymous_11) -FNDA:0,(anonymous_12) -FNDA:0,(anonymous_13) -FNDA:0,(anonymous_14) -FNDA:0,(anonymous_15) -FNDA:0,(anonymous_16) -DA:3,0 -DA:4,0 -DA:18,0 -DA:19,0 -DA:20,0 -DA:21,0 -DA:23,0 -DA:25,0 -DA:26,0 -DA:28,0 -DA:33,0 -DA:35,0 -DA:36,0 -DA:37,0 -DA:39,0 -DA:40,0 -DA:42,0 -DA:43,0 -DA:44,0 -DA:45,0 -DA:48,0 -DA:50,0 -DA:51,0 -DA:52,0 -DA:53,0 -DA:56,0 -DA:58,0 -DA:59,0 -DA:60,0 -DA:61,0 -DA:62,0 -DA:63,0 -DA:65,0 -DA:72,0 -DA:74,0 -DA:75,0 -DA:76,0 -DA:77,0 -DA:83,0 -DA:84,0 -DA:90,0 -DA:91,0 -DA:93,0 -DA:95,0 -DA:109,0 -DA:110,0 -DA:125,0 -DA:140,0 -LF:48 -LH:0 -BRDA:26,0,0,0 -BRDA:44,1,0,0 -BRDA:52,2,0,0 -BRDA:58,3,0,0 -BRDA:58,3,1,0 -BRDA:61,4,0,0 -BRDA:76,5,0,0 -BRDA:83,6,0,0 -BRDA:83,6,1,0 -BRDA:97,7,0,0 -BRDA:97,7,1,0 -BRDA:109,8,0,0 -BRDA:122,9,0,0 -BRDA:137,10,0,0 -BRF:14 -BRH:0 -end_of_record -TN: -SF:src/components/providers/AuthProvider.tsx -FN:18,AuthProvider -FNF:1 -FNH:0 -FNDA:0,AuthProvider -DA:7,0 -DA:18,0 -DA:22,0 -LF:3 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/components/study/OutputPane.tsx -FN:3,OutputPane -FNF:1 -FNH:0 -FNDA:0,OutputPane -DA:3,0 -LF:1 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/components/study/SourcePane.tsx -FN:7,SourcePane -FNF:1 -FNH:0 -FNDA:0,SourcePane -DA:7,0 -LF:1 -LH:0 -BRDA:14,0,0,0 -BRF:1 -BRH:0 -end_of_record -TN: -SF:src/components/study/SplitPane.tsx -FN:13,SplitPane -FN:25,(anonymous_2) -FN:29,(anonymous_3) -FN:36,(anonymous_4) -FNF:4 -FNH:0 -FNDA:0,SplitPane -FNDA:0,(anonymous_2) -FNDA:0,(anonymous_3) -FNDA:0,(anonymous_4) -DA:3,0 -DA:13,0 -DA:20,0 -DA:21,0 -DA:22,0 -DA:24,0 -DA:26,0 -DA:27,0 -DA:29,0 -DA:30,0 -DA:31,0 -DA:32,0 -DA:33,0 -DA:36,0 -DA:37,0 -DA:38,0 -DA:39,0 -DA:40,0 -DA:41,0 -DA:44,0 -DA:45,0 -DA:46,0 -DA:47,0 -LF:23 -LH:0 -BRDA:16,0,0,0 -BRDA:17,1,0,0 -BRDA:18,2,0,0 -BRDA:30,3,0,0 -BRDA:30,4,0,0 -BRDA:30,4,1,0 -BRF:6 -BRH:0 -end_of_record -TN: -SF:src/lib/api.ts -FN:8,(anonymous_3) -FN:23,handleResponse -FN:25,(anonymous_5) -FN:35,apiFetch -FNF:4 -FNH:0 -FNDA:0,(anonymous_3) -FNDA:0,handleResponse -FNDA:0,(anonymous_5) -FNDA:0,apiFetch -DA:2,0 -DA:7,0 -DA:9,0 -DA:11,0 -DA:13,0 -DA:14,0 -DA:24,0 -DA:25,0 -DA:26,0 -DA:32,0 -DA:35,0 -DA:39,0 -DA:41,0 -DA:45,0 -DA:46,0 -DA:49,0 -DA:50,0 -DA:53,0 -DA:59,0 -LF:19 -LH:0 -BRDA:2,0,0,0 -BRDA:2,0,1,0 -BRDA:3,1,0,0 -BRDA:3,1,1,0 -BRDA:24,2,0,0 -BRDA:28,3,0,0 -BRDA:28,3,1,0 -BRDA:28,3,2,0 -BRDA:37,4,0,0 -BRDA:45,5,0,0 -BRDA:49,6,0,0 -BRDA:49,7,0,0 -BRDA:49,7,1,0 -BRDA:56,8,0,0 -BRDA:56,8,1,0 -BRDA:56,9,0,0 -BRDA:56,9,1,0 -BRF:17 -BRH:0 -end_of_record -TN: -SF:src/lib/api/adapters.ts -FN:12,mimeToLabel -FN:27,toDocumentListRow -FN:43,toDocumentDetailView -FN:72,toDocumentPreviewView -FNF:4 -FNH:0 -FNDA:0,mimeToLabel -FNDA:0,toDocumentListRow -FNDA:0,toDocumentDetailView -FNDA:0,toDocumentPreviewView -DA:13,0 -DA:14,0 -DA:15,0 -DA:16,0 -DA:17,0 -DA:18,0 -DA:19,0 -DA:21,0 -DA:22,0 -DA:25,0 -DA:27,0 -DA:28,0 -DA:43,0 -DA:44,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:49,0 -DA:53,0 -DA:72,0 -DA:73,0 -LF:21 -LH:0 -BRDA:13,0,0,0 -BRDA:15,1,0,0 -BRDA:16,2,0,0 -BRDA:17,3,0,0 -BRDA:18,4,0,0 -BRDA:19,5,0,0 -BRDA:22,6,0,0 -BRDA:22,6,1,0 -BRDA:45,7,0,0 -BRF:9 -BRH:0 -end_of_record -TN: -SF:src/lib/api/courses.ts -FN:4,fetchCourses -FN:14,fetchCourse -FN:21,fetchCourseLessons -FN:28,createCourse -FNF:4 -FNH:0 -FNDA:0,fetchCourses -FNDA:0,fetchCourse -FNDA:0,fetchCourseLessons -FNDA:0,createCourse -DA:1,0 -DA:4,0 -DA:9,0 -DA:14,0 -DA:18,0 -DA:21,0 -DA:25,0 -DA:28,0 -DA:32,0 -LF:9 -LH:0 -BRDA:5,0,0,0 -BRDA:6,1,0,0 -BRF:2 -BRH:0 -end_of_record -TN: -SF:src/lib/api/documents.ts -FN:15,fetchDocumentsList -FN:24,fetchDocumentStatus -FN:33,fetchDocumentDetail -FN:42,fetchDocumentPreview -FN:51,uploadDocument -FN:65,deleteDocument -FN:77,getDocumentListRows -FN:85,getDocumentDetailView -FN:93,getDocumentPreviewView -FN:103,pollDocumentUntilTerminal -FN:122,(anonymous_21) -FNF:11 -FNH:0 -FNDA:0,fetchDocumentsList -FNDA:0,fetchDocumentStatus -FNDA:0,fetchDocumentDetail -FNDA:0,fetchDocumentPreview -FNDA:0,uploadDocument -FNDA:0,deleteDocument -FNDA:0,getDocumentListRows -FNDA:0,getDocumentDetailView -FNDA:0,getDocumentPreviewView -FNDA:0,pollDocumentUntilTerminal -FNDA:0,(anonymous_21) -DA:1,0 -DA:11,0 -DA:15,0 -DA:19,0 -DA:24,0 -DA:28,0 -DA:33,0 -DA:37,0 -DA:42,0 -DA:46,0 -DA:51,0 -DA:56,0 -DA:57,0 -DA:58,0 -DA:65,0 -DA:69,0 -DA:77,0 -DA:81,0 -DA:82,0 -DA:85,0 -DA:89,0 -DA:90,0 -DA:93,0 -DA:97,0 -DA:98,0 -DA:103,0 -DA:109,0 -DA:110,0 -DA:111,0 -DA:112,0 -DA:113,0 -DA:116,0 -DA:119,0 -DA:122,0 -DA:124,0 -LF:35 -LH:0 -BRDA:106,0,0,0 -BRDA:107,1,0,0 -BRDA:112,2,0,0 -BRDA:112,3,0,0 -BRDA:112,3,1,0 -BRDA:116,4,0,0 -BRDA:116,4,1,0 -BRDA:116,5,0,0 -BRDA:116,5,1,0 -BRF:9 -BRH:0 -end_of_record -TN: -SF:src/lib/api/index.ts -FNF:0 -FNH:0 -DA:1,0 -DA:2,0 -DA:3,0 -DA:4,0 -LF:4 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:src/lib/auth/config.ts -FN:14,(anonymous_2) -FN:30,(anonymous_3) -FN:55,(anonymous_4) -FN:64,(anonymous_5) -FNF:4 -FNH:0 -FNDA:0,(anonymous_2) -FNDA:0,(anonymous_3) -FNDA:0,(anonymous_4) -FNDA:0,(anonymous_5) -DA:2,0 -DA:4,0 -DA:6,0 -DA:15,0 -DA:16,0 -DA:19,0 -DA:20,0 -DA:29,0 -DA:30,0 -DA:31,0 -DA:34,0 -DA:36,0 -DA:46,0 -DA:47,0 -DA:49,0 -DA:56,0 -DA:57,0 -DA:58,0 -DA:59,0 -DA:60,0 -DA:62,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:68,0 -DA:69,0 -DA:71,0 -LF:27 -LH:0 -BRDA:4,0,0,0 -BRDA:4,0,1,0 -BRDA:15,1,0,0 -BRDA:15,2,0,0 -BRDA:15,2,1,0 -BRDA:29,3,0,0 -BRDA:31,4,0,0 -BRDA:31,4,1,0 -BRDA:37,5,0,0 -BRDA:37,5,1,0 -BRDA:38,6,0,0 -BRDA:38,6,1,0 -BRDA:39,7,0,0 -BRDA:39,7,1,0 -BRDA:40,8,0,0 -BRDA:40,8,1,0 -BRDA:41,9,0,0 -BRDA:41,9,1,0 -BRDA:42,10,0,0 -BRDA:42,10,1,0 -BRDA:43,11,0,0 -BRDA:43,11,1,0 -BRDA:46,12,0,0 -BRDA:56,13,0,0 -BRDA:65,14,0,0 -BRF:25 -BRH:0 -end_of_record -TN: -SF:src/lib/middleware/auth-guard.ts -FN:7,authMiddleware -FN:11,(anonymous_4) -FNF:2 -FNH:0 -FNDA:0,authMiddleware -FNDA:0,(anonymous_4) -DA:1,0 -DA:2,0 -DA:5,0 -DA:7,0 -DA:8,0 -DA:10,0 -DA:11,0 -DA:14,0 -DA:15,0 -DA:18,0 -DA:23,0 -DA:24,0 -DA:25,0 -DA:26,0 -DA:29,0 -DA:32,0 -LF:16 -LH:0 -BRDA:11,0,0,0 -BRDA:11,0,1,0 -BRDA:14,1,0,0 -BRDA:14,2,0,0 -BRDA:14,2,1,0 -BRDA:14,2,2,0 -BRDA:23,3,0,0 -BRF:7 -BRH:0 -end_of_record -TN: -SF:src/lib/services/courses.ts -FN:19,getCourses -FN:29,getCourse -FN:36,getCourseLessons -FN:43,getLesson -FNF:4 -FNH:0 -FNDA:0,getCourses -FNDA:0,getCourse -FNDA:0,getCourseLessons -FNDA:0,getLesson -DA:1,0 -DA:19,0 -DA:24,0 -DA:29,0 -DA:33,0 -DA:36,0 -DA:40,0 -DA:43,0 -DA:47,0 -LF:9 -LH:0 -BRDA:20,0,0,0 -BRDA:21,1,0,0 -BRF:2 -BRH:0 -end_of_record -TN: -SF:src/lib/services/documents.ts -FN:21,getDocuments -FN:30,uploadDocument -FN:45,getDocumentStatus -FN:54,deleteDocument -FN:68,pollDocumentStatus -FN:87,(anonymous_11) -FNF:6 -FNH:0 -FNDA:0,getDocuments -FNDA:0,uploadDocument -FNDA:0,getDocumentStatus -FNDA:0,deleteDocument -FNDA:0,pollDocumentStatus -FNDA:0,(anonymous_11) -DA:1,0 -DA:21,0 -DA:25,0 -DA:30,0 -DA:35,0 -DA:36,0 -DA:38,0 -DA:45,0 -DA:49,0 -DA:54,0 -DA:58,0 -DA:68,0 -DA:74,0 -DA:75,0 -DA:76,0 -DA:77,0 -DA:78,0 -DA:81,0 -DA:84,0 -DA:87,0 -DA:89,0 -LF:21 -LH:0 -BRDA:71,0,0,0 -BRDA:72,1,0,0 -BRDA:77,2,0,0 -BRDA:77,3,0,0 -BRDA:77,3,1,0 -BRDA:81,4,0,0 -BRDA:81,4,1,0 -BRDA:81,5,0,0 -BRDA:81,5,1,0 -BRF:9 -BRH:0 -end_of_record diff --git a/apps/web/package.json b/apps/web/package.json index 8d07bcb..cefe622 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -14,7 +14,7 @@ "format:check": "prettier --check \"src/**/*.{ts,tsx,json,md}\"" }, "dependencies": { - "next": "^14.0.0", + "next": "^15.5.15", "next-auth": "^4.24.0", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -32,7 +32,7 @@ "@typescript-eslint/parser": "^6.13.0", "autoprefixer": "^10.4.0", "eslint": "^8.55.0", - "eslint-config-next": "^14.0.0", + "eslint-config-next": "^15.5.15", "eslint-plugin-prettier": "^5.0.0", "eslint-plugin-react": "^7.33.0", "eslint-plugin-react-hooks": "^4.6.0", diff --git a/apps/web/src/app/courses/[courseId]/study/page.tsx b/apps/web/src/app/courses/[courseId]/study/page.tsx index cde164a..e895147 100644 --- a/apps/web/src/app/courses/[courseId]/study/page.tsx +++ b/apps/web/src/app/courses/[courseId]/study/page.tsx @@ -132,6 +132,10 @@ export default function StudyPage() {
diff --git a/apps/web/src/components/study/LessonNav.tsx b/apps/web/src/components/study/LessonNav.tsx index 7966452..aa5441b 100644 --- a/apps/web/src/components/study/LessonNav.tsx +++ b/apps/web/src/components/study/LessonNav.tsx @@ -90,7 +90,7 @@ export function LessonNav({ )} {isCompleted && ( - done + Done )} diff --git a/apps/web/src/components/study/OutputPane.tsx b/apps/web/src/components/study/OutputPane.tsx index ed574d7..bc9e108 100644 --- a/apps/web/src/components/study/OutputPane.tsx +++ b/apps/web/src/components/study/OutputPane.tsx @@ -488,7 +488,7 @@ export function OutputPane({ })} {loading && ( -
+

Retrieving · generating… @@ -543,11 +543,13 @@ export function OutputPane({ placeholder={placeholder} rows={2} disabled={loading} + aria-label="Message input" className="flex-1 resize-none rounded-md b-thin px-3 py-2 text-sm placeholder-blue-dark/40 dark:placeholder-white/40 bg-transparent outline-none focus:ring-1 focus:ring-blue-dark dark:focus:ring-white disabled:opacity-50" />