Compare commits

10 Commits

Author SHA1 Message Date
root c27e1f2689 fix api build 2026-06-12 02:40:41 -04:00
root d5903fb8d2 update deploy 2026-06-12 01:40:40 -04:00
root 47e366ea2e fix unittests 2026-06-12 01:10:23 -04:00
root 5ead80fdc7 fix tests 2026-06-11 11:46:12 -04:00
root c91fa2ce4d fix inventory 2026-06-11 11:06:32 -04:00
root 9483750161 archetecture security fix 2026-06-11 03:22:12 -04:00
root 6def9993da fix gitlab tests 2026-06-09 02:32:58 -04:00
root 20a0b6c4e5 Fix Pint formatting 2026-06-09 01:25:14 -04:00
root 6be4875c5e add tests batch 20 2026-06-09 01:03:53 -04:00
root 95efb9652e Fix PHPUnit CI test options 2026-06-09 00:23:40 -04:00
3233 changed files with 171517 additions and 37547 deletions
+85 -26
View File
@@ -1,6 +1,4 @@
# GitLab CI for Laravel 12
# Save this file as: .gitlab-ci.yml
# GitLab CI for Laravel 12 API
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
@@ -12,6 +10,7 @@ stages:
- test
- build
- security
- deploy
variables:
APP_ENV: testing
@@ -41,16 +40,19 @@ cache:
before_script:
- apt-get update
- apt-get install -y --no-install-recommends git unzip curl libzip-dev libpng-dev libonig-dev libxml2-dev libsqlite3-dev
- docker-php-ext-install mbstring zip gd
- docker-php-ext-install mbstring zip gd pdo_sqlite
- php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
- php composer-setup.php --install-dir=/usr/local/bin --filename=composer
- rm composer-setup.php
- composer install --prefer-dist --no-interaction --no-progress
# Install Pint if not present
- composer require --dev laravel/pint --ignore-platform-reqs || true
# Generate .env with real keys
- |
cat > .env <<EOF
APP_NAME=school_api
APP_ENV=testing
APP_KEY=
APP_KEY=base64:$(openssl rand -base64 32)
APP_DEBUG=false
APP_URL=http://localhost
@@ -67,21 +69,23 @@ cache:
BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
JWT_SECRET=ci_dummy_secret_not_for_production
JWT_SECRET=$(openssl rand -base64 32)
EOF
- mkdir -p database storage/framework/cache storage/framework/sessions storage/framework/views storage/logs bootstrap/cache reports
- touch database/database.sqlite
- php artisan key:generate --force
- php artisan jwt:secret --force || true # If JWT package installed
- php artisan config:clear
- php artisan view:clear
composer_validate:
extends: .php_laravel_job
stage: validate
script:
- mkdir -p reports
- bash -o pipefail -c 'composer validate --strict 2>&1 | tee reports/composer-validate.log'
- bash -o pipefail -c 'php -v 2>&1 | tee reports/php-version.log'
- bash -o pipefail -c 'php artisan --version 2>&1 | tee reports/artisan-version.log'
- composer validate --strict | tee reports/composer-validate.log
- php -v | tee reports/php-version.log
- php artisan --version | tee reports/artisan-version.log
artifacts:
when: always
expire_in: 7 days
@@ -94,60 +98,78 @@ laravel_pint:
stage: validate
script:
- mkdir -p reports
- bash -o pipefail -c 'vendor/bin/pint --test 2>&1 | tee reports/pint.log'
- vendor/bin/pint --test --format=json | tee reports/pint.json
artifacts:
when: always
expire_in: 7 days
paths:
- reports/
- storage/logs/
allow_failure: true
phpunit:
extends: .php_laravel_job
stage: test
parallel:
matrix:
- TEST_SUITE: [Unit, Feature]
script:
- mkdir -p reports
- bash -o pipefail -c 'php artisan migrate --force 2>&1 | tee reports/migrate.log'
- bash -o pipefail -c 'php artisan test --testsuite=Feature --no-interaction --log-junit reports/phpunit-feature.xml 2>&1 | tee reports/phpunit-feature.log'
- bash -o pipefail -c 'php artisan test --testsuite=Unit --no-interaction --log-junit reports/phpunit-unit.xml 2>&1 | tee reports/phpunit-unit.log'
- php artisan migrate --force | tee reports/migrate.log
- php artisan test --testsuite=$TEST_SUITE --coverage-text --log-junit reports/phpunit.xml | tee reports/phpunit.log
artifacts:
when: always
expire_in: 7 days
reports:
junit:
- reports/phpunit-feature.xml
- reports/phpunit-unit.xml
junit: reports/phpunit.xml
coverage_report:
coverage_format: cobertura
path: reports/coverage.xml
paths:
- reports/
- storage/logs/
coverage: '/^\s*Lines:\s*\d+\.\d+%/'
cache:
paths:
- .composer-cache/
- .npm-cache/
- vendor/
- node_modules/
key: ${CI_COMMIT_REF_SLUG}
build_frontend:
image: node:22-alpine
stage: build
before_script:
- npm ci
- npm ci --cache .npm --prefer-offline
script:
- mkdir -p reports
- sh -c 'npm run build 2>&1 | tee reports/npm-build.log'
- npm run build 2>&1 | tee reports/npm-build.log
artifacts:
when: always
expire_in: 7 days
paths:
- public/build/
- public/css/
- public/js/
- reports/
cache:
paths:
- .npm/
composer_audit:
extends: .php_laravel_job
stage: security
script:
- mkdir -p reports
- bash -o pipefail -c 'composer audit --locked --no-interaction 2>&1 | tee reports/composer-audit.log'
- composer audit --locked --no-interaction --format=json | tee reports/composer-audit.json
artifacts:
when: always
expire_in: 7 days
paths:
- reports/
- storage/logs/
allow_failure: true
npm_audit:
image: node:22-alpine
@@ -156,7 +178,7 @@ npm_audit:
- npm ci
script:
- mkdir -p reports
- sh -c 'npm audit --audit-level=high 2>&1 | tee reports/npm-audit.log'
- npm audit --json --audit-level=high | tee reports/npm-audit.json || true
artifacts:
when: always
expire_in: 7 days
@@ -172,14 +194,20 @@ secret_detection_basic:
script:
- mkdir -p reports
- |
echo "Scanning for obvious committed secrets..." | tee reports/secret-detection-basic.log
! grep -RInE "(APP_KEY=base64:|DB_PASSWORD=.+|JWT_SECRET=.+|MAIL_PASSWORD=.+|PAYPAL_(CLIENT|SECRET|MODE)|AKIA[0-9A-Z]{16}|-----BEGIN (RSA|OPENSSH|PRIVATE) KEY-----)" \
echo "Scanning for committed secrets..." | tee reports/secret-detection.log
if grep -RInE "(APP_KEY=base64:[A-Za-z0-9+/=]{44}|DB_PASSWORD=.+|JWT_SECRET=.+|MAIL_PASSWORD=.+|PAYPAL_(CLIENT|SECRET|MODE)|AKIA[0-9A-Z]{16}|-----BEGIN (RSA|OPENSSH|PRIVATE) KEY-----)" \
--exclude-dir=.git \
--exclude-dir=vendor \
--exclude-dir=node_modules \
--exclude=.env.example \
--exclude=.env.prod.example \
. 2>&1 | tee -a reports/secret-detection-basic.log
--exclude=reports \
. 2>&1 | tee -a reports/secret-detection.log; then
echo "❌ Secrets detected! Check reports/secret-detection.log"
exit 1
else
echo "✅ No secrets found"
fi
artifacts:
when: always
expire_in: 7 days
@@ -187,9 +215,40 @@ secret_detection_basic:
- reports/
allow_failure: false
# Optional GitLab-native security scanners.
# These run only if your GitLab tier/project supports the templates.
# Deploy to shared hosting (optional - add if needed)
deploy:
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache openssh-client sshpass rsync
script:
- echo "Deploying to production..."
- sshpass -p "$SSH_PASSWORD" rsync -avz --delete \
-e "ssh -p $SSH_PORT -o StrictHostKeyChecking=no" \
--exclude='.env' \
--exclude='storage/logs/*' \
--exclude='.git' \
--exclude='tests' \
--exclude='database/sqlite' \
./ $SSH_USER@$SSH_HOST:$SSH_TARGET_DIR/
environment:
name: production
url: $PRODUCTION_URL
only:
- main
- master
when: manual
needs:
- phpunit
- composer_audit
# Include GitLab native templates (ensure you have license)
include:
- template: Jobs/SAST.gitlab-ci.yml
- template: Jobs/Secret-Detection.gitlab-ci.yml
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
# Optional: Run SAST only on main branch
sast:
rules:
- if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "master"'
+1
View File
@@ -0,0 +1 @@
cookie
@@ -0,0 +1 @@
2026-06-11T07:11:03.205132Z WARN turborepo_filewatch: failed to wait for initial filesystem cookie: filewatching failed to start: waiting for cookie timed out: deadline has elapsed
+16
View File
@@ -0,0 +1,16 @@
FROM node:20-bookworm
WORKDIR /app
RUN npm install -g npm@10.5.0 --no-fund --no-audit
RUN corepack enable
COPY package.json package-lock.json turbo.json tsconfig.base.json ./
COPY apps ./apps
COPY packages ./packages
RUN npm ci --no-fund --no-audit
EXPOSE 3000 3001 3002 3003 4000
CMD ["sh", "-c", "npm run db:generate && npm run dev"]
+58
View File
@@ -0,0 +1,58 @@
FROM node:20-bookworm AS builder
WORKDIR /app
RUN corepack enable && corepack prepare npm@10.5.0 --activate
COPY package.json package-lock.json turbo.json tsconfig.base.json ./
COPY apps ./apps
COPY packages ./packages
# These URLs are read by Next.js config during `next build`, so the production
# image must bake Docker-network service URLs instead of localhost defaults.
ARG API_INTERNAL_URL=http://api:4000/api/v1
ARG DASHBOARD_INTERNAL_URL=http://dashboard:3001
ARG ADMIN_INTERNAL_URL=http://admin:3002
# NEXT_PUBLIC_* vars must be present at build time — they are inlined into JS bundles
ARG NEXT_PUBLIC_API_URL
ARG NEXT_PUBLIC_MARKETPLACE_URL
ARG NEXT_PUBLIC_DASHBOARD_URL
ARG NEXT_PUBLIC_ADMIN_URL
ENV API_INTERNAL_URL=$API_INTERNAL_URL \
DASHBOARD_INTERNAL_URL=$DASHBOARD_INTERNAL_URL \
ADMIN_INTERNAL_URL=$ADMIN_INTERNAL_URL \
NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL \
NEXT_PUBLIC_MARKETPLACE_URL=$NEXT_PUBLIC_MARKETPLACE_URL \
NEXT_PUBLIC_DASHBOARD_URL=$NEXT_PUBLIC_DASHBOARD_URL \
NEXT_PUBLIC_ADMIN_URL=$NEXT_PUBLIC_ADMIN_URL
RUN npm install
RUN npm run db:generate
RUN npm run build
FROM node:20-bookworm AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN corepack enable && corepack prepare npm@10.5.0 --activate \
&& groupadd --system --gid 10001 app \
&& useradd --system --uid 10001 --gid app --home-dir /app --shell /usr/sbin/nologin app \
&& mkdir -p /var/lib/rentaldrivego/storage/public /var/lib/rentaldrivego/storage/private /tmp/rentaldrivego \
&& chown -R app:app /app /var/lib/rentaldrivego /tmp/rentaldrivego
COPY --from=builder --chown=app:app /app/package.json /app/package-lock.json /app/turbo.json /app/tsconfig.base.json ./
COPY --from=builder --chown=app:app /app/node_modules ./node_modules
COPY --from=builder --chown=app:app /app/apps ./apps
COPY --from=builder --chown=app:app /app/packages ./packages
COPY --chown=root:root docker/entrypoint.production.sh /usr/local/bin/rdg-entrypoint.sh
RUN chmod 755 /usr/local/bin/rdg-entrypoint.sh
ENTRYPOINT ["/usr/local/bin/rdg-entrypoint.sh"]
EXPOSE 3000 3001 3002 4000
CMD ["npm", "run", "start", "--workspace", "@rentaldrivego/api"]
+15
View File
@@ -0,0 +1,15 @@
FROM node:20-bookworm
WORKDIR /app
RUN corepack enable && corepack prepare npm@10.5.0 --activate
COPY package.json package-lock.json turbo.json tsconfig.base.json ./
COPY apps ./apps
COPY packages ./packages
RUN npm install
ENV NODE_ENV=test
CMD ["sh", "-c", "npm run db:deploy && npm run db:generate && npm run type-check && npm run build && npm run test:api:integration"]
@@ -0,0 +1,183 @@
import { useCallback, useEffect, useState } from 'react'
import { Link, useSearchParams } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import { fetchInventoryDashboard } from '../../api/inventory'
import { INVENTORY_BOOK_BASE } from './inventoryPaths'
/**
* Inventory Dashboard — summary counts by type, low stock, out of stock, etc.
* Backend: GET /api/v1/inventory/dashboard
*/
export function InventoryDashboardPage() {
const [searchParams] = useSearchParams()
const [data, setData] = useState<Record<string, unknown>>({})
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const load = useCallback(() => {
setLoading(true)
fetchInventoryDashboard(searchParams)
.then((res) => {
if (res && typeof res === 'object') {
setData(res as Record<string, unknown>)
}
setError(null)
})
.catch((e: unknown) => {
setError(e instanceof ApiHttpError ? e.message : 'Unable to load dashboard.')
})
.finally(() => setLoading(false))
}, [searchParams])
useEffect(() => {
load()
}, [load])
const byType = (data.by_type as Record<string, number>) ?? {}
const totalItems = Number(data.total_items ?? 0)
const lowStockCount = Number(data.low_stock_count ?? 0)
const outOfStockCount = Number(data.out_of_stock_count ?? 0)
const needsRepairCount = Number(data.needs_repair_count ?? 0)
const missingCount = Number(data.missing_count ?? 0)
return (
<div className="container-fluid px-0 mt-3">
<div className="d-flex justify-content-between align-items-center mb-3 px-3 flex-wrap gap-2">
<h3 className="mb-0">Inventory Dashboard</h3>
<div className="d-flex gap-2">
<Link className="btn btn-outline-info btn-sm" to="/app/administrator/inventory/stock-status">
Stock Status
</Link>
<Link className="btn btn-outline-secondary" to={INVENTORY_BOOK_BASE}>
Back to Items
</Link>
</div>
</div>
{error ? <div className="alert alert-danger mx-3">{error}</div> : null}
{loading ? (
<p className="text-muted px-3">Loading</p>
) : (
<div className="row g-3 px-3">
{/* Summary Cards */}
<div className="col-sm-6 col-lg-4">
<div className="card border-primary h-100">
<div className="card-body text-center">
<h5 className="card-title text-primary">{totalItems}</h5>
<p className="card-text">Total Items</p>
</div>
</div>
</div>
<div className="col-sm-6 col-lg-4">
<div className="card border-warning h-100">
<div className="card-body text-center">
<h5 className="card-title text-warning">{lowStockCount}</h5>
<p className="card-text">Low Stock Items</p>
{lowStockCount > 0 ? (
<Link className="btn btn-sm btn-warning" to="/app/administrator/inventory/low-stock">
View Low Stock
</Link>
) : null}
</div>
</div>
</div>
<div className="col-sm-6 col-lg-4">
<div className="card border-danger h-100">
<div className="card-body text-center">
<h5 className="card-title text-danger">{outOfStockCount}</h5>
<p className="card-text">Out of Stock</p>
</div>
</div>
</div>
<div className="col-sm-6 col-lg-4">
<div className="card border-info h-100">
<div className="card-body text-center">
<h5 className="card-title text-info">{needsRepairCount}</h5>
<p className="card-text">Needs Repair</p>
</div>
</div>
</div>
<div className="col-sm-6 col-lg-4">
<div className="card border-secondary h-100">
<div className="card-body text-center">
<h5 className="card-title text-secondary">{missingCount}</h5>
<p className="card-text">Missing / Cannot Find</p>
</div>
</div>
</div>
{/* Items by Type */}
<div className="col-12">
<div className="card">
<div className="card-header">Items by Type</div>
<div className="card-body">
{Object.keys(byType).length === 0 ? (
<p className="text-muted mb-0">No items found.</p>
) : (
<div className="table-responsive">
<table className="table table-striped align-middle mb-0">
<thead>
<tr>
<th>Type</th>
<th className="text-end">Count</th>
</tr>
</thead>
<tbody>
{Object.entries(byType).map(([type, count]) => (
<tr key={type}>
<td style={{ textTransform: 'capitalize' }}>{type}</td>
<td className="text-end">{Number(count).toLocaleString()}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</div>
</div>
</div>
{/* Quick Links */}
<div className="col-12">
<div className="card">
<div className="card-header">Quick Actions</div>
<div className="card-body">
<div className="d-flex gap-2 flex-wrap">
<Link className="btn btn-outline-primary" to="/app/administrator/inventory/classroom">
Classroom Equipment
</Link>
<Link className="btn btn-outline-primary" to={INVENTORY_BOOK_BASE}>
Books
</Link>
<Link className="btn btn-outline-primary" to="/app/administrator/inventory/office">
Office Supplies
</Link>
<Link className="btn btn-outline-primary" to="/app/administrator/inventory/kitchen">
Kitchen Supplies
</Link>
<Link className="btn btn-outline-primary" to="/app/administrator/inventory/movements">
Movements
</Link>
<Link className="btn btn-outline-primary" to="/app/administrator/inventory/summary">
Summary
</Link>
<Link className="btn btn-outline-primary" to="/app/administrator/inventory/reorder-suggestions">
Reorder Suggestions
</Link>
<Link className="btn btn-outline-primary" to="/app/administrator/inventory/low-stock">
Low Stock
</Link>
</div>
</div>
</div>
</div>
</div>
)}
</div>
)
}
@@ -0,0 +1,112 @@
import { useCallback, useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import { fetchLowStock } from '../../api/inventory'
import { INVENTORY_BOOK_BASE } from './inventoryPaths'
/**
* Low Stock Items — items where quantity <= reorder_point.
* Backend: GET /api/v1/inventory/low-stock
*/
export function InventoryLowStockPage() {
const [items, setItems] = useState<Record<string, unknown>[]>([])
const [count, setCount] = useState(0)
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const load = useCallback(() => {
setLoading(true)
fetchLowStock()
.then((res) => {
if (res && typeof res === 'object') {
const o = res as Record<string, unknown>
const arr = Array.isArray(o.items) ? (o.items as Record<string, unknown>[]) : []
setItems(arr)
setCount(Number(o.count ?? arr.length))
}
setError(null)
})
.catch((e: unknown) => {
setError(e instanceof ApiHttpError ? e.message : 'Unable to load low stock items.')
})
.finally(() => setLoading(false))
}, [])
useEffect(() => {
load()
}, [load])
return (
<div className="container-fluid px-0 mt-3">
<div className="d-flex justify-content-between align-items-center mb-3 px-3 flex-wrap gap-2">
<h3 className="mb-0">Low Stock Items ({count})</h3>
<div className="d-flex gap-2">
<Link className="btn btn-outline-info btn-sm" to="/app/administrator/inventory/reorder-suggestions">
Reorder Suggestions
</Link>
<Link className="btn btn-outline-secondary" to={INVENTORY_BOOK_BASE}>
Back to Items
</Link>
</div>
</div>
{error ? <div className="alert alert-danger mx-3">{error}</div> : null}
{loading ? (
<p className="text-muted px-3">Loading</p>
) : items.length === 0 ? (
<div className="alert alert-success mx-3">
<strong>All stocked up!</strong> No items are below their reorder point.
</div>
) : (
<div className="card mx-3">
<div className="card-body table-responsive">
<table className="table table-striped align-middle" id="lowStockTable">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Category</th>
<th className="text-end">Current Qty</th>
<th className="text-end">Reorder Point</th>
<th className="text-end">Reorder Qty</th>
<th className="text-end">Lead Time (Days)</th>
<th>Preferred Supplier</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{items.map((item) => {
const i = item as Record<string, unknown>
const supplier = i.preferred_supplier as Record<string, unknown> | null
return (
<tr key={String(i.id)}>
<td>{String(i.name ?? '')}</td>
<td style={{ textTransform: 'capitalize' }}>{String(i.type ?? '')}</td>
<td>{String((i.category as Record<string, unknown>)?.name ?? i.category ?? '')}</td>
<td className="text-end text-danger fw-semibold">
{Number(i.quantity ?? 0).toLocaleString()}
</td>
<td className="text-end">{Number(i.reorder_point ?? 0).toLocaleString()}</td>
<td className="text-end">{Number(i.reorder_quantity ?? 0).toLocaleString() || '—'}</td>
<td className="text-end">{Number(i.lead_time_days ?? 0) || '—'}</td>
<td>{supplier ? String(supplier.name ?? '') : '—'}</td>
<td>
<Link
className="btn btn-sm btn-warning"
to={`/app/administrator/inventory/items/${String(i.id)}/adjust`}
>
Adjust Stock
</Link>
</td>
</tr>
)
})}
</tbody>
</table>
</div>
</div>
)}
</div>
)
}
@@ -0,0 +1,109 @@
import { useCallback, useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import { fetchReorderSuggestions } from '../../api/inventory'
import { INVENTORY_BOOK_BASE } from './inventoryPaths'
/**
* Reorder Suggestions — calculated suggested order quantities for low-stock items.
* Backend: GET /api/v1/inventory/reorder-suggestions
*/
export function InventoryReorderSuggestionsPage() {
const [suggestions, setSuggestions] = useState<Record<string, unknown>[]>([])
const [count, setCount] = useState(0)
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const load = useCallback(() => {
setLoading(true)
fetchReorderSuggestions()
.then((res) => {
if (res && typeof res === 'object') {
const o = res as Record<string, unknown>
const arr = Array.isArray(o.suggestions) ? (o.suggestions as Record<string, unknown>[]) : []
setSuggestions(arr)
setCount(Number(o.count ?? arr.length))
}
setError(null)
})
.catch((e: unknown) => {
setError(e instanceof ApiHttpError ? e.message : 'Unable to load reorder suggestions.')
})
.finally(() => setLoading(false))
}, [])
useEffect(() => {
load()
}, [load])
return (
<div className="container-fluid px-0 mt-3">
<div className="d-flex justify-content-between align-items-center mb-3 px-3 flex-wrap gap-2">
<h3 className="mb-0">Reorder Suggestions ({count})</h3>
<div className="d-flex gap-2">
<Link className="btn btn-outline-warning btn-sm" to="/app/administrator/inventory/low-stock">
Low Stock
</Link>
<Link className="btn btn-outline-secondary" to={INVENTORY_BOOK_BASE}>
Back to Items
</Link>
</div>
</div>
{error ? <div className="alert alert-danger mx-3">{error}</div> : null}
{loading ? (
<p className="text-muted px-3">Loading</p>
) : suggestions.length === 0 ? (
<div className="alert alert-success mx-3">
<strong>All stocked up!</strong> No reorder suggestions at this time.
</div>
) : (
<div className="card mx-3">
<div className="card-body table-responsive">
<table className="table table-striped align-middle" id="reorderSuggestionsTable">
<thead>
<tr>
<th>Name</th>
<th>Category</th>
<th className="text-end">Current Qty</th>
<th className="text-end">Reorder Point</th>
<th className="text-end">Suggested Order</th>
<th>Preferred Supplier</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{suggestions.map((s) => {
const supplier = s.preferred_supplier as Record<string, unknown> | null
return (
<tr key={String(s.id)}>
<td>{String(s.name ?? '')}</td>
<td>{String(s.category ?? '—')}</td>
<td className="text-end text-danger fw-semibold">
{Number(s.current_quantity ?? 0).toLocaleString()}
</td>
<td className="text-end">{Number(s.reorder_point ?? 0).toLocaleString()}</td>
<td className="text-end fw-semibold">
{Number(s.suggested_order_qty ?? 0).toLocaleString()}
</td>
<td>{supplier ? String(supplier.name ?? '') : '—'}</td>
<td>
<Link
className="btn btn-sm btn-warning"
to={`/app/administrator/inventory/items/${String(s.id)}/adjust`}
>
Adjust Stock
</Link>
</td>
</tr>
)
})}
</tbody>
</table>
</div>
</div>
)}
</div>
)
}
@@ -0,0 +1,167 @@
import { useCallback, useEffect, useState } from 'react'
import { Link, useSearchParams } from 'react-router-dom'
import { ApiHttpError } from '../../api/http'
import { fetchStockStatus } from '../../api/inventory'
import { INVENTORY_BOOK_BASE } from './inventoryPaths'
/**
* Stock Status — all items with status: ok/low_stock/out_of_stock.
* Backend: GET /api/v1/inventory/stock-status
*/
export function InventoryStockStatusPage() {
const [searchParams, setSearchParams] = useSearchParams()
const [items, setItems] = useState<Record<string, unknown>[]>([])
const [counts, setCounts] = useState<Record<string, number>>({})
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const load = useCallback(() => {
setLoading(true)
fetchStockStatus(searchParams)
.then((res) => {
if (res && typeof res === 'object') {
const o = res as Record<string, unknown>
setItems(Array.isArray(o.items) ? (o.items as Record<string, unknown>[]) : [])
setCounts((o.counts as Record<string, number>) ?? {})
}
setError(null)
})
.catch((e: unknown) => {
setError(e instanceof ApiHttpError ? e.message : 'Unable to load stock status.')
})
.finally(() => setLoading(false))
}, [searchParams])
useEffect(() => {
load()
}, [load])
function onTypeFilter(v: string) {
const next = new URLSearchParams(searchParams)
if (v) next.set('type', v)
else next.delete('type')
setSearchParams(next)
}
const currentType = searchParams.get('type') ?? ''
return (
<div className="container-fluid px-0 mt-3">
<div className="d-flex justify-content-between align-items-center mb-3 px-3 flex-wrap gap-2">
<h3 className="mb-0">Stock Status</h3>
<div className="d-flex gap-2">
<Link className="btn btn-outline-warning btn-sm" to="/app/administrator/inventory/low-stock">
Low Stock
</Link>
<Link className="btn btn-outline-info btn-sm" to="/app/administrator/inventory/reorder-suggestions">
Reorder Suggestions
</Link>
<Link className="btn btn-outline-secondary" to={INVENTORY_BOOK_BASE}>
Back to Items
</Link>
</div>
</div>
{error ? <div className="alert alert-danger mx-3">{error}</div> : null}
{loading ? (
<p className="text-muted px-3">Loading</p>
) : (
<>
{/* Summary Badges */}
<div className="d-flex gap-3 mb-3 px-3 flex-wrap">
<span className="badge bg-success fs-6">
OK: {counts.ok ?? 0}
</span>
<span className="badge bg-warning fs-6">
Low Stock: {counts.low_stock ?? 0}
</span>
<span className="badge bg-danger fs-6">
Out of Stock: {counts.out_of_stock ?? 0}
</span>
</div>
<div className="card mx-3">
<div className="card-header d-flex justify-content-between align-items-center flex-wrap gap-2">
<span>All Items</span>
<select
className="form-select form-select-sm"
style={{ minWidth: 180 }}
value={currentType}
onChange={(e) => onTypeFilter(e.target.value)}
>
<option value="">All Types</option>
<option value="book">Books</option>
<option value="classroom">Classroom</option>
<option value="office">Office</option>
<option value="kitchen">Kitchen</option>
</select>
</div>
<div className="card-body table-responsive">
<table className="table table-striped align-middle" id="stockStatusTable">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Category</th>
<th className="text-end">Quantity</th>
<th className="text-end">Reorder Point</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{items.length === 0 ? (
<tr>
<td colSpan={7} className="text-center text-muted py-4">
No items found.
</td>
</tr>
) : (
items.map((item) => {
const status = String(item.status ?? 'ok')
const badgeClass =
status === 'out_of_stock'
? 'bg-danger'
: status === 'low_stock'
? 'bg-warning'
: 'bg-success'
const badgeLabel =
status === 'out_of_stock'
? 'Out of Stock'
: status === 'low_stock'
? 'Low Stock'
: 'OK'
return (
<tr key={String(item.id)}>
<td>{String(item.name ?? '')}</td>
<td style={{ textTransform: 'capitalize' }}>{String(item.type ?? '')}</td>
<td>{String(item.category ?? '—')}</td>
<td className="text-end">{Number(item.quantity ?? 0).toLocaleString()}</td>
<td className="text-end">
{item.reorder_point != null ? Number(item.reorder_point).toLocaleString() : '—'}
</td>
<td>
<span className={`badge ${badgeClass}`}>{badgeLabel}</span>
</td>
<td>
<Link
className="btn btn-sm btn-outline-primary me-1"
to={`/app/administrator/inventory/items/${String(item.id)}/adjust`}
>
Adjust
</Link>
</td>
</tr>
)
})
)}
</tbody>
</table>
</div>
</div>
</>
)}
</div>
)
}
@@ -0,0 +1,79 @@
<?php
namespace App\Console\Commands;
use App\Services\Inventory\InventoryMovementService;
use Illuminate\Console\Command;
class InventoryReconcile extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'inventory:reconcile
{--school-year= : The school year to reconcile (e.g., 2025-2026). Defaults to current.}
{--fix : Automatically fix discrepancies by creating adjustment movements.}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Reconcile inventory item quantities against movement ledger totals';
/**
* Execute the console command.
*/
public function handle(InventoryMovementService $movementService)
{
$schoolYear = $this->option('school-year');
$autoFix = $this->option('fix');
$result = $movementService->reconcile($schoolYear);
$this->info("School Year: {$result['school_year']}");
$this->info("Total Items: {$result['total_items']}");
$this->info("Discrepancies: {$result['discrepancies_count']}");
if (empty($result['discrepancies'])) {
$this->info('✅ All item quantities match movement ledger.');
return Command::SUCCESS;
}
$this->table(
['ID', 'Name', 'Stored Qty', 'Movement Sum', 'Variance'],
collect($result['discrepancies'])->map(fn ($d) => [
$d['id'],
$d['name'],
$d['stored_quantity'],
$d['movement_sum'],
$d['variance'],
])->toArray()
);
if ($autoFix) {
$this->info('Fixing discrepancies...');
foreach ($result['discrepancies'] as $d) {
if ($d['variance'] !== 0) {
$movementService->recordMovement(
itemId: $d['id'],
qtyChange: -$d['variance'],
type: 'adjust',
reason: 'Auto-reconciliation: stored qty differed from movement sum',
note: 'Reconciled from '.$d['stored_quantity'].' to '.$d['movement_sum'],
performedBy: null
);
$this->line(" Fixed item #{$d['id']} ({$d['name']}): variance was {$d['variance']}");
}
}
$this->info('✅ Fix applied.');
} else {
$this->warn('Run with --fix to automatically correct discrepancies.');
}
return Command::SUCCESS;
}
}
@@ -8,6 +8,7 @@ use App\Services\Auth\ApiLoginSecurityService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth;
class AuthController extends BaseApiController
@@ -24,6 +25,11 @@ class AuthController extends BaseApiController
$password = (string) ($payload['password'] ?? '');
if ($email === '' || $password === '') {
Log::notice('api_login: missing credentials', [
'ip' => (string) $request->ip(),
'email' => $this->maskEmail($email),
]);
return response()->json([
'status' => false,
'message' => 'Email and password are required.',
@@ -32,6 +38,11 @@ class AuthController extends BaseApiController
$ip = $request->ip();
if ($security->isIpBlocked((string) $ip)) {
Log::notice('api_login: ip blocked', [
'ip' => (string) $ip,
'email' => $this->maskEmail($email),
]);
return response()->json([
'status' => false,
'message' => 'Too many failed attempts from your IP. Please try again later.',
@@ -41,6 +52,24 @@ class AuthController extends BaseApiController
$user = User::query()->whereRaw('LOWER(email) = ?', [$email])->first();
if (! $user) {
$security->logIpAttempt((string) $ip);
Log::notice('api_login: unknown email', [
'ip' => (string) $ip,
'email' => $this->maskEmail($email),
]);
return response()->json([
'status' => false,
'message' => 'Invalid email or password.',
], 401);
}
if (blank($user->password)) {
$security->logIpAttempt((string) $ip);
Log::notice('api_login: password missing', [
'ip' => (string) $ip,
'email' => $this->maskEmail($email),
'user_id' => (int) $user->id,
]);
return response()->json([
'status' => false,
@@ -50,6 +79,12 @@ class AuthController extends BaseApiController
if (! verify_stored_password($password, (string) $user->password)) {
$security->handleFailedLogin($user, $email, (string) $ip);
Log::notice('api_login: password mismatch', [
'ip' => (string) $ip,
'email' => $this->maskEmail($email),
'user_id' => (int) $user->id,
'failed_attempts' => (int) ($user->fresh()?->failed_attempts ?? 0),
]);
return response()->json([
'status' => false,
@@ -60,6 +95,12 @@ class AuthController extends BaseApiController
// Suspension is checked AFTER credentials are verified so that the
// response shape cannot be used to enumerate which emails exist.
if ($user->is_suspended) {
Log::notice('api_login: suspended account', [
'ip' => (string) $ip,
'email' => $this->maskEmail($email),
'user_id' => (int) $user->id,
]);
return response()->json([
'status' => false,
'message' => 'Account suspended. Please reset your password.',
@@ -71,6 +112,12 @@ class AuthController extends BaseApiController
$fresh = $user->fresh();
if (! $fresh) {
Log::warning('api_login: fresh user reload failed after successful verification', [
'ip' => (string) $ip,
'email' => $this->maskEmail($email),
'user_id' => (int) $user->id,
]);
return response()->json([
'status' => false,
'message' => 'Invalid email or password.',
@@ -82,6 +129,19 @@ class AuthController extends BaseApiController
return response()->json($security->buildLoginResponse($fresh, $jwtToken));
}
private function maskEmail(string $email): string
{
$email = trim(strtolower($email));
if ($email === '' || ! str_contains($email, '@')) {
return $email;
}
[$local, $domain] = explode('@', $email, 2);
$localPrefix = substr($local, 0, min(2, strlen($local)));
return $localPrefix.str_repeat('*', max(strlen($local) - strlen($localPrefix), 0)).'@'.$domain;
}
public function refresh(Request $request): JsonResponse
{
try {
@@ -12,6 +12,7 @@ use App\Services\Auth\AuthSessionService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth;
/**
@@ -89,6 +90,11 @@ class AuthSessionController extends Controller
$ip = (string) $request->ip();
if ($this->security->isIpBlocked($ip)) {
Log::notice('session_login: ip blocked', [
'ip' => $ip,
'email' => $this->maskEmail($email),
]);
return response()->json([
'status' => false,
'message' => 'Too many failed attempts from your IP. Please try again later.',
@@ -99,6 +105,24 @@ class AuthSessionController extends Controller
if (! $user) {
$this->security->logIpAttempt($ip);
Log::notice('session_login: unknown email', [
'ip' => $ip,
'email' => $this->maskEmail($email),
]);
return response()->json([
'status' => false,
'message' => 'The email and password combination you entered is invalid. Please try again.',
], 401);
}
if (blank($user->password)) {
$this->security->logIpAttempt($ip);
Log::notice('session_login: password missing', [
'ip' => $ip,
'email' => $this->maskEmail($email),
'user_id' => (int) $user->id,
]);
return response()->json([
'status' => false,
@@ -107,6 +131,12 @@ class AuthSessionController extends Controller
}
if ($user->is_suspended) {
Log::notice('session_login: suspended account', [
'ip' => $ip,
'email' => $this->maskEmail($email),
'user_id' => (int) $user->id,
]);
return response()->json([
'status' => false,
'message' => 'Account suspended. Please check your email to reset your password.',
@@ -115,6 +145,12 @@ class AuthSessionController extends Controller
if (! verify_stored_password($password, (string) $user->password)) {
$this->security->handleFailedLogin($user, $email, $ip);
Log::notice('session_login: password mismatch', [
'ip' => $ip,
'email' => $this->maskEmail($email),
'user_id' => (int) $user->id,
'failed_attempts' => (int) ($user->fresh()?->failed_attempts ?? 0),
]);
return response()->json([
'status' => false,
@@ -124,6 +160,12 @@ class AuthSessionController extends Controller
$fresh = $user->fresh();
if (! $fresh) {
Log::warning('session_login: fresh user reload failed after successful verification', [
'ip' => $ip,
'email' => $this->maskEmail($email),
'user_id' => (int) $user->id,
]);
return response()->json([
'status' => false,
'message' => 'The email and password combination you entered is invalid. Please try again.',
@@ -151,6 +193,19 @@ class AuthSessionController extends Controller
]));
}
private function maskEmail(string $email): string
{
$email = trim(strtolower($email));
if ($email === '' || ! str_contains($email, '@')) {
return $email;
}
[$local, $domain] = explode('@', $email, 2);
$localPrefix = substr($local, 0, min(2, strlen($local)));
return $localPrefix.str_repeat('*', max(strlen($local) - strlen($localPrefix), 0)).'@'.$domain;
}
/** Closes the current web session. */
public function logout(Request $request): JsonResponse
{
@@ -0,0 +1,398 @@
<?php
namespace App\Http\Controllers\Api\CompetitionWinners;
use App\Http\Controllers\Api\Core\BaseApiController;
use App\Http\Requests\Admin\SaveCompetitionScoresRequest;
use App\Http\Requests\Admin\StoreCompetitionWinnerRequest;
use App\Http\Requests\Admin\UpdateCompetitionWinnerRequest;
use App\Services\Admin\CompetitionWinners\CompetitionWinnersAdminService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class CompetitionWinnersController extends BaseApiController
{
public function __construct(
private CompetitionWinnersAdminService $service,
) {
parent::__construct();
}
public function index(): JsonResponse
{
$guard = $this->authenticatedAdminOrForbidden();
if ($guard instanceof JsonResponse) {
return $guard;
}
$payload = $this->service->indexData();
return response()->json([
'ok' => true,
'competitions' => array_values(array_map(
fn ($row) => $this->normalizeCompetitionRow($this->rowToArray($row)),
$this->iterableToArray($payload['competitions'] ?? [])
)),
'sectionMap' => $payload['sectionMap'] ?? [],
]);
}
public function createForm(): JsonResponse
{
$guard = $this->authenticatedAdminOrForbidden();
if ($guard instanceof JsonResponse) {
return $guard;
}
return response()->json([
'ok' => true,
...$this->service->createFormData(),
]);
}
public function settingsForm(int $id): JsonResponse
{
$guard = $this->authenticatedAdminOrForbidden();
if ($guard instanceof JsonResponse) {
return $guard;
}
$payload = $this->service->settingsFormData($id);
if ($payload === null) {
return response()->json([
'ok' => false,
'message' => 'Competition not found.',
], Response::HTTP_NOT_FOUND);
}
return response()->json([
'ok' => true,
...$payload,
]);
}
public function store(StoreCompetitionWinnerRequest $request): JsonResponse
{
$guard = $this->authenticatedAdminOrForbidden();
if ($guard instanceof JsonResponse) {
return $guard;
}
$validated = $request->validated();
$id = $this->service->storeCompetition(
$validated,
(array) ($validated['winner_overrides'] ?? []),
(array) ($validated['question_counts'] ?? []),
(array) ($validated['prizes'] ?? []),
$guard
);
return response()->json([
'ok' => true,
'message' => 'Competition created.',
'id' => $id,
], Response::HTTP_CREATED);
}
public function update(UpdateCompetitionWinnerRequest $request, int $id): JsonResponse
{
$guard = $this->authenticatedAdminOrForbidden();
if ($guard instanceof JsonResponse) {
return $guard;
}
$validated = $request->validated();
$updated = $this->service->updateCompetition(
$id,
$validated,
(array) ($validated['winner_overrides'] ?? []),
(array) ($validated['question_counts'] ?? []),
(array) ($validated['prizes'] ?? [])
);
if (! $updated) {
return response()->json([
'ok' => false,
'message' => 'Competition not found.',
], Response::HTTP_NOT_FOUND);
}
return response()->json([
'ok' => true,
'message' => 'Competition updated.',
'id' => $id,
]);
}
public function scores(Request $request, int $id): JsonResponse
{
$guard = $this->authenticatedAdminOrForbidden();
if ($guard instanceof JsonResponse) {
return $guard;
}
$payload = $this->service->editScoresData($id, $this->intOrNull($request->query('class_section_id')));
if ($payload === null) {
return response()->json([
'ok' => false,
'message' => 'Competition not found.',
], Response::HTTP_NOT_FOUND);
}
return response()->json([
'ok' => true,
...$payload,
]);
}
public function saveScores(SaveCompetitionScoresRequest $request, int $id): JsonResponse
{
$guard = $this->authenticatedAdminOrForbidden();
if ($guard instanceof JsonResponse) {
return $guard;
}
$competition = $this->service->editScoresData($id, $this->intOrNull($request->input('class_section_id')));
if ($competition === null) {
return response()->json([
'ok' => false,
'message' => 'Competition not found.',
], Response::HTTP_NOT_FOUND);
}
$payload = $request->validated();
$saved = $this->service->saveScores(
$id,
(array) ($payload['scores'] ?? []),
$this->intOrNull($payload['class_section_id'] ?? null),
(array) ($competition['competition'] ?? [])
);
if (! $saved) {
return response()->json([
'ok' => false,
'message' => 'Select a class section before saving scores.',
], Response::HTTP_UNPROCESSABLE_ENTITY);
}
return response()->json([
'ok' => true,
'message' => 'Scores saved.',
'savedCount' => count((array) ($payload['scores'] ?? [])),
]);
}
public function preview(int $id): JsonResponse
{
$guard = $this->authenticatedAdminOrForbidden();
if ($guard instanceof JsonResponse) {
return $guard;
}
$payload = $this->service->previewData($id);
if ($payload === null) {
return response()->json([
'ok' => false,
'message' => 'Competition not found.',
], Response::HTTP_NOT_FOUND);
}
return response()->json([
'ok' => true,
...$payload,
]);
}
public function winners(int $id): JsonResponse
{
$guard = $this->authenticatedAdminOrForbidden();
if ($guard instanceof JsonResponse) {
return $guard;
}
$payload = $this->service->settingsFormData($id);
if ($payload === null || ! isset($payload['competition'])) {
return response()->json([
'ok' => false,
'message' => 'Competition not found.',
], Response::HTTP_NOT_FOUND);
}
return response()->json([
'ok' => true,
'competition' => $payload['competition'],
'rows' => $this->service->winnersListingRows($id),
'sectionMap' => $this->service->getClassSectionMap(),
]);
}
public function publish(int $id): JsonResponse
{
$guard = $this->authenticatedAdminOrForbidden();
if ($guard instanceof JsonResponse) {
return $guard;
}
if (! $this->service->publishWinners($id)) {
return response()->json([
'ok' => false,
'message' => 'Competition not found.',
], Response::HTTP_NOT_FOUND);
}
return response()->json([
'ok' => true,
'message' => 'Competition winners published.',
]);
}
public function lock(int $id): JsonResponse
{
$guard = $this->authenticatedAdminOrForbidden();
if ($guard instanceof JsonResponse) {
return $guard;
}
if (! $this->service->lockCompetition($id, $guard)) {
return response()->json([
'ok' => false,
'message' => 'Competition not found.',
], Response::HTTP_NOT_FOUND);
}
return response()->json([
'ok' => true,
'message' => 'Competition locked.',
]);
}
public function unlock(int $id): JsonResponse
{
$guard = $this->authenticatedAdminOrForbidden();
if ($guard instanceof JsonResponse) {
return $guard;
}
if (! $this->service->unlockCompetition($id)) {
return response()->json([
'ok' => false,
'message' => 'Competition not found.',
], Response::HTTP_NOT_FOUND);
}
return response()->json([
'ok' => true,
'message' => 'Competition unlocked.',
]);
}
public function exportQuiz(Request $request, int $id): JsonResponse
{
$guard = $this->authenticatedAdminOrForbidden();
if ($guard instanceof JsonResponse) {
return $guard;
}
$validated = $request->validate([
'class_section_id' => ['nullable', 'integer'],
'semester' => ['nullable', 'string'],
'school_year' => ['nullable', 'string'],
]);
$schoolId = $this->intOrNull(optional(auth()->user())->school_id);
$result = $this->service->exportCompetitionToQuiz(
$id,
$this->intOrNull($validated['class_section_id'] ?? null) ?? 0,
$schoolId,
$guard,
$validated['semester'] ?? null,
$validated['school_year'] ?? null
);
return response()->json($result, $result['ok'] ? Response::HTTP_OK : Response::HTTP_UNPROCESSABLE_ENTITY);
}
private function authenticatedAdminOrForbidden(): int|JsonResponse
{
$user = $this->getCurrentUser();
if (! $user || (int) ($user->id ?? 0) <= 0) {
return response()->json(['ok' => false, 'message' => 'Unauthorized.'], Response::HTTP_UNAUTHORIZED);
}
$roles = array_map('strtolower', (array) ($user->roles ?? []));
$allowed = ['administrator', 'admin', 'principal', 'vice_principal', 'vice-principal'];
if (empty(array_intersect($roles, $allowed))) {
return response()->json(['ok' => false, 'message' => 'Forbidden.'], Response::HTTP_FORBIDDEN);
}
return (int) $user->id;
}
/**
* @param iterable<mixed> $rows
* @return array<int, mixed>
*/
private function iterableToArray(iterable $rows): array
{
return is_array($rows) ? $rows : iterator_to_array($rows, false);
}
/**
* @param array<string, mixed> $row
* @return array<string, mixed>
*/
private function normalizeCompetitionRow(array $row): array
{
$id = $this->intOrNull($row['id'] ?? $row['competition_id'] ?? null);
if ($id !== null) {
$row['id'] = $id;
}
$classSectionId = $this->intOrNull($row['class_section_id'] ?? null);
$row['class_section_id'] = $classSectionId;
$row['is_locked'] = (bool) ($row['is_locked'] ?? false);
$row['is_published'] = (bool) ($row['is_published'] ?? false);
return $row;
}
/**
* @return array<string, mixed>
*/
private function rowToArray(mixed $row): array
{
if (is_array($row)) {
return $row;
}
if ($row instanceof \JsonSerializable) {
$serialized = $row->jsonSerialize();
if (is_array($serialized)) {
return $serialized;
}
}
if (is_object($row) && method_exists($row, 'toArray')) {
$array = $row->toArray();
if (is_array($array)) {
return $array;
}
}
return (array) $row;
}
private function intOrNull(mixed $value): ?int
{
if ($value === null || $value === '') {
return null;
}
if (is_numeric($value)) {
return (int) $value;
}
return null;
}
}
@@ -8,6 +8,7 @@ use App\Http\Requests\Payments\PaymentManualUpdateRequest;
use App\Services\Payments\PaymentManualService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
class PaymentManualController extends BaseApiController
@@ -70,18 +71,26 @@ class PaymentManualController extends BaseApiController
$payload = $request->validated();
$result = $this->service->recordPayment(
$invoiceId,
(float) $payload['amount'],
(string) $payload['payment_method'],
$payload['payment_date'] ?? null,
$payload['check_number'] ?? null,
$payload['payment_type'] ?? null,
$request->file('payment_file'),
$payload['school_year'] ?? null,
$payload['semester'] ?? null,
$guard
);
try {
$result = $this->service->recordPayment(
$invoiceId,
(float) $payload['amount'],
(string) $payload['payment_method'],
$payload['payment_date'] ?? null,
$payload['check_number'] ?? null,
$payload['payment_type'] ?? null,
$request->file('payment_file'),
$payload['school_year'] ?? null,
$payload['semester'] ?? null,
$guard
);
} catch (\InvalidArgumentException $e) {
return response()->json(['ok' => false, 'message' => $e->getMessage()], 422);
} catch (\Throwable $e) {
Log::error('Manual payment record failed: '.$e->getMessage());
return response()->json(['ok' => false, 'message' => 'Unable to record payment.'], 400);
}
return response()->json(['ok' => true] + $result);
}
@@ -95,14 +104,22 @@ class PaymentManualController extends BaseApiController
$payload = $request->validated();
$this->service->editPayment(
$paymentId,
(float) $payload['paid_amount'],
(string) $payload['payment_method'],
$payload['check_number'] ?? null,
$request->file('payment_file'),
$guard
);
try {
$this->service->editPayment(
$paymentId,
(float) $payload['paid_amount'],
(string) $payload['payment_method'],
$payload['check_number'] ?? null,
$request->file('payment_file'),
$guard
);
} catch (\InvalidArgumentException $e) {
return response()->json(['ok' => false, 'message' => $e->getMessage()], 422);
} catch (\Throwable $e) {
Log::error('Manual payment edit failed: '.$e->getMessage());
return response()->json(['ok' => false, 'message' => 'Unable to update payment.'], 400);
}
return response()->json(['ok' => true]);
}
@@ -11,7 +11,9 @@ use App\Http\Requests\Inventory\InventoryItemUpdateRequest;
use App\Http\Requests\Inventory\InventoryTeacherDistributionRequest;
use App\Http\Requests\Inventory\InventoryTeacherDistributionStoreRequest;
use App\Http\Resources\Inventory\InventoryItemResource;
use App\Models\InventoryItem;
use App\Services\Inventory\InventoryItemService;
use App\Services\Inventory\InventoryMovementService;
use App\Services\Inventory\InventorySummaryService;
use App\Services\Inventory\InventoryTeacherDistributionService;
use Illuminate\Http\JsonResponse;
@@ -23,7 +25,8 @@ class InventoryController extends BaseApiController
public function __construct(
private InventoryItemService $items,
private InventorySummaryService $summary,
private InventoryTeacherDistributionService $distribution
private InventoryTeacherDistributionService $distribution,
private InventoryMovementService $movementService
) {
parent::__construct();
}
@@ -185,6 +188,161 @@ class InventoryController extends BaseApiController
return $this->success($result);
}
/**
* Get low-stock items (where quantity <= reorder_point).
*/
public function lowStock(): JsonResponse
{
$items = InventoryItem::lowStock()
->with('category', 'preferredSupplier')
->orderBy('name')
->get();
return $this->success([
'items' => InventoryItemResource::collection($items),
'count' => $items->count(),
]);
}
/**
* Get reorder suggestions based on low-stock items.
*/
public function reorderSuggestions(): JsonResponse
{
$lowStockItems = InventoryItem::lowStock()
->with('category', 'preferredSupplier')
->orderBy('name')
->get();
$suggestions = $lowStockItems->map(function ($item) {
$reorderQty = (int) ($item->reorder_quantity ?: 0);
$currentQty = (int) $item->quantity;
$reorderPoint = (int) ($item->reorder_point ?: 0);
// If no reorder quantity is set, suggest enough to bring back above reorder point
if ($reorderQty <= 0) {
$reorderQty = max(1, $reorderPoint - $currentQty + 5);
}
return [
'id' => $item->id,
'name' => $item->name,
'current_quantity' => $currentQty,
'reorder_point' => $reorderPoint,
'suggested_order_qty' => $reorderQty,
'preferred_supplier' => $item->preferredSupplier ? [
'id' => $item->preferredSupplier->id,
'name' => $item->preferredSupplier->name,
] : null,
'category' => $item->category ? $item->category->name : null,
];
});
return $this->success([
'suggestions' => $suggestions,
'count' => $suggestions->count(),
]);
}
/**
* Create a reorder request for a low-stock item.
*/
public function reorderRequest(int $id): JsonResponse
{
$item = InventoryItem::with('preferredSupplier')->find($id);
if (! $item) {
return $this->error('Item not found.', Response::HTTP_NOT_FOUND);
}
$reorderQty = (int) ($item->reorder_quantity ?: 0);
if ($reorderQty <= 0) {
$reorderQty = max(1, ((int) ($item->reorder_point ?: 0)) - ((int) $item->quantity) + 5);
}
return $this->success([
'item_id' => $item->id,
'item_name' => $item->name,
'current_quantity' => (int) $item->quantity,
'suggested_quantity' => $reorderQty,
'preferred_supplier' => $item->preferredSupplier ? [
'id' => $item->preferredSupplier->id,
'name' => $item->preferredSupplier->name,
] : null,
]);
}
/**
* View all items with their stock status.
*/
public function stockStatus(): JsonResponse
{
$type = request()->query('type');
$items = InventoryItem::query()
->with('category', 'preferredSupplier')
->when($type, fn ($q) => $q->where('type', $type))
->orderBy('name')
->get()
->map(function ($item) {
$qty = (int) $item->quantity;
$reorderPoint = (int) ($item->reorder_point ?: 0);
$status = 'ok';
if ($qty <= 0) {
$status = 'out_of_stock';
} elseif ($reorderPoint > 0 && $qty <= $reorderPoint) {
$status = 'low_stock';
}
return [
'id' => $item->id,
'name' => $item->name,
'type' => $item->type,
'category' => $item->category ? $item->category->name : null,
'quantity' => $qty,
'reorder_point' => $reorderPoint,
'status' => $status,
];
});
$counts = [
'ok' => $items->where('status', 'ok')->count(),
'low_stock' => $items->where('status', 'low_stock')->count(),
'out_of_stock' => $items->where('status', 'out_of_stock')->count(),
];
return $this->success([
'items' => $items,
'counts' => $counts,
]);
}
/**
* Inventory dashboard summary.
*/
public function dashboard(): JsonResponse
{
$schoolYear = request()->query('school_year');
$items = InventoryItem::query()
->when($schoolYear, fn ($q) => $q->where('school_year', $schoolYear))
->get();
$totalItems = $items->count();
$byType = $items->groupBy('type')->map(fn ($g) => $g->count());
$lowStockCount = $items->filter(fn ($i) => $i->reorder_point && $i->quantity <= $i->reorder_point)->count();
$outOfStockCount = $items->filter(fn ($i) => $i->quantity <= 0)->count();
$needsRepairCount = $items->sum('needs_repair_qty');
$missingCount = $items->sum('cannot_find_qty');
return $this->success([
'total_items' => $totalItems,
'by_type' => $byType,
'low_stock_count' => $lowStockCount,
'out_of_stock_count' => $outOfStockCount,
'needs_repair_count' => (int) $needsRepairCount,
'missing_count' => (int) $missingCount,
]);
}
private function authenticatedUserIdOrUnauthorized(): int|JsonResponse
{
$userId = (int) (auth()->id() ?? 0);
@@ -73,6 +73,57 @@ class InventoryMovementController extends BaseApiController
return $this->success($result);
}
/**
* Void a movement (append-only correction).
*/
public function void(int $id): JsonResponse
{
$actor = $this->authenticatedUserIdOrUnauthorized();
if ($actor instanceof JsonResponse) {
return $actor;
}
$reason = (string) request()->input('reason', '');
if (empty(trim($reason))) {
return $this->error('Reason is required to void a movement.', Response::HTTP_UNPROCESSABLE_ENTITY);
}
$result = $this->movements->voidMovement($id, $reason, $actor);
if (! ($result['ok'] ?? false)) {
return $this->error($result['message'] ?? 'Failed to void movement.', Response::HTTP_UNPROCESSABLE_ENTITY);
}
return $this->success(['message' => 'Movement voided successfully.']);
}
/**
* Create a correction movement.
*/
public function correct(int $id): JsonResponse
{
$actor = $this->authenticatedUserIdOrUnauthorized();
if ($actor instanceof JsonResponse) {
return $actor;
}
$qtyChange = (int) request()->input('qty_change', 0);
$reason = (string) request()->input('reason', '');
if ($qtyChange === 0) {
return $this->error('Quantity change must be non-zero.', Response::HTTP_UNPROCESSABLE_ENTITY);
}
if (empty(trim($reason))) {
return $this->error('Reason is required.', Response::HTTP_UNPROCESSABLE_ENTITY);
}
$result = $this->movements->correctMovement($id, $qtyChange, $reason, $actor);
if (! ($result['ok'] ?? false)) {
return $this->error($result['message'] ?? 'Failed to correct movement.', Response::HTTP_UNPROCESSABLE_ENTITY);
}
return $this->success(['message' => 'Correction movement created.']);
}
private function authenticatedUserIdOrUnauthorized(): int|JsonResponse
{
$userId = (int) (auth()->id() ?? 0);
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Api;
use App\Models\Stats;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Symfony\Component\HttpFoundation\Response;
class StatsController extends BaseApiController
@@ -11,6 +12,10 @@ class StatsController extends BaseApiController
public function index()
{
try {
if (! Schema::hasTable('stats')) {
return $this->success([], 'Statistics retrieved successfully');
}
$stats = Stats::query()->get()->toArray();
return $this->success($stats, 'Statistics retrieved successfully');
@@ -192,17 +192,17 @@ class StudentController extends BaseApiController
'firstname' => ['required', 'string', 'max:150'],
'lastname' => ['required', 'string', 'max:150'],
'dob' => ['nullable', 'date'],
'age' => ['nullable', 'integer', 'min:0'],
'gender' => ['nullable', 'string', 'max:20'],
'age' => ['required', 'integer', 'min:0'],
'gender' => ['required', 'string', 'max:20'],
'is_active' => ['nullable', 'boolean'],
'registration_grade' => ['nullable', 'string', 'max:50'],
'is_new' => ['nullable', 'boolean'],
'photo_consent' => ['nullable', 'boolean'],
'parent_id' => ['nullable', 'integer', 'min:1'],
'photo_consent' => ['required', 'boolean'],
'parent_id' => ['required', 'integer', 'min:1'],
'registration_date' => ['nullable', 'date'],
'tuition_paid' => ['nullable', 'boolean'],
'semester' => ['nullable', 'string', 'max:50'],
'year_of_registration' => ['nullable', 'integer', 'min:1900'],
'year_of_registration' => ['required', 'integer', 'min:1900'],
'school_year' => ['required', 'string', 'max:50'],
'medical_conditions' => ['nullable', 'string'],
'allergies' => ['nullable', 'string'],
@@ -229,7 +229,26 @@ class StudentController extends BaseApiController
}
$payload = $validator->validated();
$student = Student::query()->create($payload);
$studentPayload = collect($payload)->only([
'school_id',
'firstname',
'lastname',
'dob',
'age',
'gender',
'is_active',
'registration_grade',
'is_new',
'photo_consent',
'parent_id',
'registration_date',
'tuition_paid',
'semester',
'year_of_registration',
'school_year',
])->all();
$student = Student::query()->create($studentPayload);
if (empty($student->school_id)) {
$student->school_id = $this->generateSchoolId($student->id);
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Api\System;
use App\Http\Controllers\Api\Core\BaseApiController;
use App\Models\Stats;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Symfony\Component\HttpFoundation\Response;
class StatsController extends BaseApiController
@@ -12,6 +13,10 @@ class StatsController extends BaseApiController
public function index()
{
try {
if (! Schema::hasTable('stats')) {
return $this->success([], 'Statistics retrieved successfully');
}
$stats = Stats::query()->get()->toArray();
return $this->success($stats, 'Statistics retrieved successfully');
@@ -14,13 +14,13 @@ class InventoryItemStoreRequest extends ApiFormRequest
public function rules(): array
{
return [
'type' => ['required', 'string', 'max:20'],
'category_id' => ['nullable', 'integer', 'min:1'],
'type' => ['required', 'string', 'in:classroom,book,office,kitchen'],
'category_id' => ['nullable', 'integer', 'min:1', 'exists:inventory_categories,id'],
'name' => ['required', 'string', 'max:255'],
'description' => ['nullable', 'string'],
'quantity' => ['nullable', 'integer'],
'quantity' => ['nullable', 'integer', 'min:0'],
'unit' => ['nullable', 'string', 'max:50'],
'condition' => ['nullable', 'string', 'max:50'],
'condition' => ['nullable', 'string', 'in:good,needs_repair,need_replace,cannot_find'],
'isbn' => ['nullable', 'string', 'max:50'],
'edition' => ['nullable', 'string', 'max:50'],
'sku' => ['nullable', 'string', 'max:50'],
@@ -14,12 +14,12 @@ class InventoryItemUpdateRequest extends ApiFormRequest
public function rules(): array
{
return [
'category_id' => ['nullable', 'integer', 'min:1'],
'category_id' => ['nullable', 'integer', 'min:1', 'exists:inventory_categories,id'],
'name' => ['sometimes', 'string', 'max:255'],
'description' => ['nullable', 'string'],
'quantity' => ['nullable', 'integer'],
// quantity is intentionally excluded: stock changes must go through movements
'unit' => ['nullable', 'string', 'max:50'],
'condition' => ['nullable', 'string', 'max:50'],
'condition' => ['nullable', 'string', 'in:good,needs_repair,need_replace,cannot_find'],
'isbn' => ['nullable', 'string', 'max:50'],
'edition' => ['nullable', 'string', 'max:50'],
'sku' => ['nullable', 'string', 'max:50'],
@@ -28,6 +28,16 @@ class InventoryItemResource extends JsonResource
'semester' => $this['semester'] ?? null,
'school_year' => $this['school_year'] ?? null,
'updated_by' => $this['updated_by'] ?? null,
// New fields
'preferred_supplier_id' => $this['preferred_supplier_id'] ?? null,
'last_purchase_price' => $this['last_purchase_price'] ?? null,
'average_unit_cost' => $this['average_unit_cost'] ?? null,
'reorder_point' => $this['reorder_point'] ?? null,
'reorder_quantity' => $this['reorder_quantity'] ?? null,
'lead_time_days' => $this['lead_time_days'] ?? null,
'barcode' => $this['barcode'] ?? null,
'qr_code' => $this['qr_code'] ?? null,
'asset_tag' => $this['asset_tag'] ?? null,
];
}
}
+39
View File
@@ -28,6 +28,17 @@ class InventoryItem extends BaseModel
'needs_repair_qty',
'need_replace_qty',
'cannot_find_qty',
// Supplier/reorder fields
'preferred_supplier_id',
'last_purchase_price',
'average_unit_cost',
'reorder_point',
'reorder_quantity',
'lead_time_days',
// Barcode/QR fields
'barcode',
'qr_code',
'asset_tag',
];
protected $casts = [
@@ -39,6 +50,13 @@ class InventoryItem extends BaseModel
'needs_repair_qty' => 'integer',
'need_replace_qty' => 'integer',
'cannot_find_qty' => 'integer',
'preferred_supplier_id' => 'integer',
'last_purchase_price' => 'decimal:2',
'average_unit_cost' => 'decimal:2',
'reorder_point' => 'integer',
'reorder_quantity' => 'integer',
'lead_time_days' => 'integer',
];
/* Optional relationships */
@@ -46,4 +64,25 @@ class InventoryItem extends BaseModel
{
return $this->belongsTo(InventoryCategory::class, 'category_id');
}
public function preferredSupplier()
{
return $this->belongsTo(Supplier::class, 'preferred_supplier_id');
}
public function movements()
{
return $this->hasMany(InventoryMovement::class, 'item_id');
}
public function scopeLowStock($query)
{
return $query->whereNotNull('reorder_point')
->whereColumn('quantity', '<=', 'reorder_point');
}
public function scopeOutOfStock($query)
{
return $query->where('quantity', '<=', 0);
}
}
+37
View File
@@ -21,6 +21,13 @@ class InventoryMovement extends BaseModel
'teacher_id',
'student_id',
'class_section_id',
// Audit/correction fields
'voided_at',
'voided_by',
'void_reason',
'corrects_movement_id',
'source_type',
'source_id',
];
protected $casts = [
@@ -30,8 +37,23 @@ class InventoryMovement extends BaseModel
'teacher_id' => 'integer',
'student_id' => 'integer',
'class_section_id' => 'integer',
'voided_by' => 'integer',
'corrects_movement_id' => 'integer',
'source_id' => 'integer',
'voided_at' => 'datetime',
];
/* Scopes */
public function scopeNotVoided($query)
{
return $query->whereNull('voided_at');
}
public function scopeVoided($query)
{
return $query->whereNotNull('voided_at');
}
/* Optional relationships */
public function item()
{
@@ -57,4 +79,19 @@ class InventoryMovement extends BaseModel
{
return $this->belongsTo(ClassSection::class, 'class_section_id');
}
public function voidedBy()
{
return $this->belongsTo(User::class, 'voided_by');
}
public function correctsMovement()
{
return $this->belongsTo(self::class, 'corrects_movement_id');
}
public function corrections()
{
return $this->hasMany(self::class, 'corrects_movement_id');
}
}
+1
View File
@@ -11,6 +11,7 @@ class PurchaseOrderItem extends BaseModel
protected $fillable = [
'purchase_order_id',
'supply_id',
'inventory_item_id',
'description',
'quantity',
'received_qty',
+1
View File
@@ -31,6 +31,7 @@ class Student extends BaseModel
'is_new',
'parent_id',
'school_year',
'semester',
'registration_date',
'tuition_paid',
'year_of_registration',
+8 -2
View File
@@ -724,8 +724,14 @@ class User extends Authenticatable implements JWTSubject
return;
}
// Avoid double-hashing
$this->attributes['password'] = str_starts_with((string) $value, '$2y$')
$value = (string) $value;
$hashInfo = password_get_info($value);
$hashParts = preg_split('/[:$]/', $value);
$isPbkdf2Hash = is_array($hashParts) && count($hashParts) === 4;
// Avoid double-hashing when callers already pass a password_hash()
// value or one of the legacy PBKDF2 hashes used by this codebase.
$this->attributes['password'] = (($hashInfo['algo'] ?? null) !== null || $isPbkdf2Hash)
? $value
: Hash::make($value);
}
@@ -4,9 +4,12 @@ namespace App\Services\Administrator;
use App\Models\Configuration;
use Carbon\Carbon;
use Illuminate\Support\Facades\Schema;
class AdministratorSharedService
{
protected ?bool $teacherClassHasSemesterColumn = null;
public function __construct(
protected Configuration $configuration
) {}
@@ -150,4 +153,13 @@ class AdministratorSharedService
return count(array_unique($ids));
}
public function teacherClassSupportsSemester(): bool
{
if ($this->teacherClassHasSemesterColumn !== null) {
return $this->teacherClassHasSemesterColumn;
}
return $this->teacherClassHasSemesterColumn = Schema::hasColumn('teacher_class', 'semester');
}
}
@@ -142,13 +142,18 @@ class TeacherSubmissionNotificationService
return [];
}
return ClassSection::query()
$query = ClassSection::query()
->select('teacher_class.class_section_id', 'teacher_class.teacher_id')
->join('teacher_class', 'teacher_class.class_section_id', '=', 'classSection.class_section_id')
->whereIn('teacher_class.teacher_id', $teacherIds)
->where('teacher_class.school_year', $schoolYear)
->where('teacher_class.semester', $semester)
->orderBy('teacher_class.class_section_id')
->orderBy('teacher_class.class_section_id');
if ($this->shared->teacherClassSupportsSemester() && $semester !== '') {
$query->where('teacher_class.semester', $semester);
}
return $query
->get()
->map(static fn ($row): array => [
'class_section_id' => (int) $row->class_section_id,
@@ -20,8 +20,9 @@ class TeacherSubmissionReportService
{
$semester = $this->shared->getSemester($filters['semester'] ?? null);
$schoolYear = $this->shared->getSchoolYear($filters['school_year'] ?? null);
$teacherClassSupportsSemester = $this->shared->teacherClassSupportsSemester();
$assignmentRows = DB::table('teacher_class as tc')
$assignmentQuery = DB::table('teacher_class as tc')
->select([
'tc.class_section_id',
'cs.class_section_name',
@@ -33,8 +34,13 @@ class TeacherSubmissionReportService
->leftJoin('classSection as cs', 'cs.class_section_id', '=', 'tc.class_section_id')
->leftJoin('users as u', 'u.id', '=', 'tc.teacher_id')
->where('tc.school_year', $schoolYear)
->where('tc.semester', $semester)
->orderBy('cs.class_section_name')
->orderBy('cs.class_section_name');
if ($teacherClassSupportsSemester && $semester !== '') {
$assignmentQuery->where('tc.semester', $semester);
}
$assignmentRows = $assignmentQuery
->get()
->map(fn ($r) => (array) $r)
->all();
@@ -15,6 +15,7 @@ class InventoryMovementService
{
$selectedYear = trim((string) ($filters['school_year'] ?? $this->context->schoolYear()));
$selectedSem = trim((string) ($filters['semester'] ?? $this->context->semester()));
$includeVoided = ! empty($filters['include_voided']);
$builder = DB::table('inventory_movements as m')
->select([
@@ -32,6 +33,11 @@ class InventoryMovementService
->leftJoin('classSection as cs', 'cs.class_section_id', '=', 'm.class_section_id')
->orderBy('m.id', 'DESC');
// Exclude voided movements by default
if (! $includeVoided) {
$builder->whereNull('m.voided_at');
}
if ($selectedYear !== '') {
$builder->where('m.school_year', $selectedYear);
}
@@ -42,6 +48,10 @@ class InventoryMovementService
return $builder->get()->map(fn ($r) => (array) $r)->all();
}
/**
* @deprecated Use recordMovement() instead. This method allows editing
* movement history which weakens auditability.
*/
public function create(array $data, int $performedBy = 0): array
{
$itemId = (int) ($data['item_id'] ?? 0);
@@ -58,19 +68,7 @@ class InventoryMovementService
return ['ok' => false, 'message' => 'Not enough stock to apply this movement.'];
}
$payload = [
'item_id' => $itemId,
'qty_change' => $qtyChange,
'movement_type' => $movementType,
'reason' => trim((string) ($data['reason'] ?? '')),
'note' => trim((string) ($data['note'] ?? '')),
'semester' => $data['semester'] ?? $this->context->semester(),
'school_year' => $data['school_year'] ?? $this->context->schoolYear(),
'performed_by' => $performedBy ?: null,
'teacher_id' => $this->nullableInt($data['teacher_id'] ?? null),
'student_id' => $this->nullableInt($data['student_id'] ?? null),
'class_section_id' => $this->nullableInt($data['class_section_id'] ?? null),
];
$payload = $this->buildMovementPayload($data, $itemId, $qtyChange, $movementType, $performedBy);
try {
InventoryMovement::query()->create($payload);
@@ -84,6 +82,10 @@ class InventoryMovementService
return ['ok' => true];
}
/**
* @deprecated Do NOT edit movements directly. Use voidMovement() + recordMovement() instead.
* Editing historical movements destroys audit integrity.
*/
public function update(int $id, array $data): array
{
$movement = InventoryMovement::query()->find($id);
@@ -91,6 +93,11 @@ class InventoryMovementService
return ['ok' => false, 'message' => 'Movement not found.'];
}
// Prevent editing voided movements
if ($movement->voided_at) {
return ['ok' => false, 'message' => 'Cannot edit a voided movement.'];
}
$movementType = (string) ($data['movement_type'] ?? $movement->movement_type);
$qtyChange = (int) ($data['qty_change'] ?? $movement->qty_change);
$qtyChange = $this->normalizeMovementQty($movementType, $qtyChange);
@@ -125,6 +132,10 @@ class InventoryMovementService
return ['ok' => true];
}
/**
* @deprecated Do NOT hard-delete movements. Use voidMovement() instead.
* Deleting historical movements destroys audit integrity.
*/
public function delete(int $id): array
{
$movement = InventoryMovement::query()->find($id);
@@ -132,6 +143,14 @@ class InventoryMovementService
return ['ok' => false, 'message' => 'Movement not found.'];
}
// Prevent hard-deleting movements that have corrections
$hasCorrections = InventoryMovement::query()
->where('corrects_movement_id', $id)
->exists();
if ($hasCorrections) {
return ['ok' => false, 'message' => 'Cannot delete a movement that has corrections. Void it instead.'];
}
$itemId = (int) $movement->item_id;
try {
$movement->delete();
@@ -147,6 +166,10 @@ class InventoryMovementService
return ['ok' => true];
}
/**
* @deprecated Do NOT bulk-delete movements. Use voidMovement() instead.
* Deleting historical movements destroys audit integrity.
*/
public function bulkDelete(array $ids): array
{
$ids = array_values(array_filter(array_map('intval', $ids), static fn ($v) => $v > 0));
@@ -154,6 +177,14 @@ class InventoryMovementService
return ['ok' => false, 'message' => 'No movements selected.'];
}
// Check for corrections
$hasCorrections = InventoryMovement::query()
->whereIn('corrects_movement_id', $ids)
->exists();
if ($hasCorrections) {
return ['ok' => false, 'message' => 'Cannot delete movements that have corrections. Void them instead.'];
}
$itemIds = DB::table('inventory_movements')
->select('item_id')
->whereIn('id', $ids)
@@ -178,6 +209,10 @@ class InventoryMovementService
return ['ok' => true, 'deleted' => count($ids)];
}
/**
* Record a new inventory movement (append-only).
* This is the primary method for all stock changes.
*/
public function recordMovement(
int $itemId,
int $qtyChange,
@@ -223,11 +258,109 @@ class InventoryMovementService
return true;
}
/**
* Void an existing movement (append-only correction).
* The original movement is preserved but marked as voided.
*/
public function voidMovement(int $movementId, string $reason, int $voidedBy): array
{
$movement = InventoryMovement::query()->find($movementId);
if (! $movement) {
return ['ok' => false, 'message' => 'Movement not found.'];
}
if ($movement->voided_at) {
return ['ok' => false, 'message' => 'Movement is already voided.'];
}
$itemId = (int) $movement->item_id;
try {
DB::transaction(function () use ($movement, $reason, $voidedBy, $itemId) {
// Mark original as voided
$movement->update([
'voided_at' => now(),
'voided_by' => $voidedBy,
'void_reason' => $reason,
]);
// Create reverse movement to correct the quantity
$reverseQty = -(int) $movement->qty_change;
if ($reverseQty !== 0) {
InventoryMovement::query()->create([
'item_id' => $itemId,
'qty_change' => $reverseQty,
'movement_type' => 'adjust',
'reason' => 'Correction: voided movement #'.$movement->id,
'note' => $reason,
'semester' => $this->context->semester(),
'school_year' => $this->context->schoolYear(),
'performed_by' => $voidedBy,
'corrects_movement_id' => $movement->id,
]);
}
$this->recalcQuantity($itemId);
});
} catch (\Throwable $e) {
Log::error('Inventory movement void failed: '.$e->getMessage());
return ['ok' => false, 'message' => 'Could not void movement.'];
}
return ['ok' => true];
}
/**
* Create a correction movement for an existing movement.
* This does NOT void the original; it adds an adjusting entry.
*/
public function correctMovement(int $movementId, int $correctedQtyChange, string $reason, int $performedBy): array
{
$movement = InventoryMovement::query()->find($movementId);
if (! $movement) {
return ['ok' => false, 'message' => 'Movement not found.'];
}
if ($movement->voided_at) {
return ['ok' => false, 'message' => 'Cannot correct a voided movement.'];
}
$itemId = (int) $movement->item_id;
if ($this->wouldGoNegative($itemId, $correctedQtyChange)) {
return ['ok' => false, 'message' => 'Not enough stock to apply correction.'];
}
try {
InventoryMovement::query()->create([
'item_id' => $itemId,
'qty_change' => $correctedQtyChange,
'movement_type' => 'adjust',
'reason' => 'Correction for movement #'.$movement->id,
'note' => $reason,
'semester' => $this->context->semester(),
'school_year' => $this->context->schoolYear(),
'performed_by' => $performedBy,
'corrects_movement_id' => $movement->id,
]);
$this->recalcQuantity($itemId);
} catch (\Throwable $e) {
Log::error('Inventory movement correction failed: '.$e->getMessage());
return ['ok' => false, 'message' => 'Could not correct movement.'];
}
return ['ok' => true];
}
public function recalcQuantity(int $itemId): void
{
$sumRow = InventoryMovement::query()
->selectRaw('SUM(qty_change) as qty_change')
->where('item_id', $itemId)
->whereNull('voided_at') // Exclude voided movements from calculations
->first();
$sum = (int) ($sumRow?->qty_change ?? 0);
@@ -258,6 +391,47 @@ class InventoryMovementService
}
}
/**
* Reconcile inventory items - compare stored quantity against movement totals.
* Returns an array of items that have discrepancies.
*/
public function reconcile(?string $schoolYear = null): array
{
$schoolYear = $schoolYear ?: $this->context->schoolYear();
$discrepancies = [];
$items = InventoryItem::query()
->when($schoolYear, fn ($q) => $q->where('school_year', $schoolYear))
->get();
foreach ($items as $item) {
$movementSum = (int) InventoryMovement::query()
->where('item_id', $item->id)
->whereNull('voided_at')
->sum('qty_change');
$storedQty = (int) $item->quantity;
$variance = $storedQty - $movementSum;
if ($variance !== 0) {
$discrepancies[] = [
'id' => $item->id,
'name' => $item->name,
'stored_quantity' => $storedQty,
'movement_sum' => $movementSum,
'variance' => $variance,
];
}
}
return [
'school_year' => $schoolYear,
'total_items' => $items->count(),
'discrepancies_count' => count($discrepancies),
'discrepancies' => $discrepancies,
];
}
private function ensureInitialMovement(int $itemId): void
{
$hasMov = InventoryMovement::query()->where('item_id', $itemId)->exists();
@@ -345,4 +519,21 @@ class InventoryMovementService
return (int) $val;
}
private function buildMovementPayload(array $data, int $itemId, int $qtyChange, string $movementType, int $performedBy): array
{
return [
'item_id' => $itemId,
'qty_change' => $qtyChange,
'movement_type' => $movementType,
'reason' => trim((string) ($data['reason'] ?? '')),
'note' => trim((string) ($data['note'] ?? '')),
'semester' => $data['semester'] ?? $this->context->semester(),
'school_year' => $data['school_year'] ?? $this->context->schoolYear(),
'performed_by' => $performedBy ?: null,
'teacher_id' => $this->nullableInt($data['teacher_id'] ?? null),
'student_id' => $this->nullableInt($data['student_id'] ?? null),
'class_section_id' => $this->nullableInt($data['class_section_id'] ?? null),
];
}
}
@@ -6,11 +6,16 @@ use App\Models\PurchaseOrder;
use App\Models\PurchaseOrderItem;
use App\Models\Supply;
use App\Models\SupplyTransaction;
use App\Services\Inventory\InventoryMovementService;
use Illuminate\Support\Facades\DB;
use RuntimeException;
class PurchaseOrderReceiveService
{
public function __construct(
private InventoryMovementService $inventoryMovementService
) {}
public function receive(int $poId, array $received, string $issuedBy): array
{
$po = PurchaseOrder::query()->find($poId);
@@ -52,25 +57,36 @@ class PurchaseOrderReceiveService
$poItem->received_qty = (int) $poItem->received_qty + $toReceive;
$poItem->save();
// Update supply qty_on_hand (legacy support)
$supply = Supply::query()->find($poItem->supply_id);
if (! $supply) {
$completed = false;
if ($supply) {
$supply->qty_on_hand = (int) $supply->qty_on_hand + $toReceive;
$supply->save();
continue;
SupplyTransaction::query()->create([
'supply_id' => $supply->id,
'type' => 'in',
'quantity' => $toReceive,
'ref' => 'PO '.($po->po_number ?? $po->id),
'issued_to' => 'Inventory',
'issued_by' => $issuedBy,
'notes' => 'Received against PO',
]);
}
$supply->qty_on_hand = (int) $supply->qty_on_hand + $toReceive;
$supply->save();
SupplyTransaction::query()->create([
'supply_id' => $supply->id,
'type' => 'in',
'quantity' => $toReceive,
'ref' => 'PO '.($po->po_number ?? $po->id),
'issued_to' => 'Inventory',
'issued_by' => $issuedBy,
'notes' => 'Received against PO',
]);
// Create inventory movement if the PO item is linked to an inventory item
$inventoryItemId = $poItem->inventory_item_id;
if ($inventoryItemId) {
$performedBy = is_numeric($issuedBy) ? (int) $issuedBy : null;
$this->inventoryMovementService->recordMovement(
itemId: (int) $inventoryItemId,
qtyChange: $toReceive,
type: 'in',
reason: 'Purchase order received',
note: 'PO '.($po->po_number ?? $po->id),
performedBy: $performedBy
);
}
if ($poItem->received_qty < $poItem->quantity) {
$completed = false;
@@ -164,22 +164,27 @@ class RefundOverpaymentService
->select('id', 'parent_id', 'total_amount', 'school_year')
->where('school_year', $schoolYear)
->get()
->map(fn ($row) => (array) $row)
->map(fn ($row) => method_exists($row, 'toArray') ? $row->toArray() : (array) $row)
->filter(fn (array $row) => isset($row['id'], $row['parent_id']))
->values()
->all();
if (empty($invRows)) {
return ['created_ids' => [], 'updated_ids' => []];
}
$invoiceIds = array_map(static fn ($row) => (int) $row['id'], $invRows);
$invoiceIds = array_values(array_filter(array_map(static fn ($row) => (int) ($row['id'] ?? 0), $invRows)));
$paidByInv = $this->sumPaymentsByInvoice($invoiceIds);
$discByInv = $this->sumDiscountsByInvoice($invoiceIds);
$refByInv = $this->sumRefundsByInvoice($invoiceIds);
foreach ($invRows as $inv) {
$iid = (int) $inv['id'];
$pid = (int) $inv['parent_id'];
$iid = (int) ($inv['id'] ?? 0);
$pid = (int) ($inv['parent_id'] ?? 0);
if ($iid <= 0 || $pid <= 0) {
continue;
}
$total = (float) ($inv['total_amount'] ?? 0);
$paid = (float) ($paidByInv[$iid] ?? 0);
$disc = (float) ($discByInv[$iid] ?? 0);
+1
View File
@@ -0,0 +1 @@
jRlQg50qYlv2hlr5AFzlp
@@ -0,0 +1,23 @@
{
"/_global-error/page": "/_global-error",
"/_not-found/page": "/_not-found",
"/auth-redirect/page": "/auth-redirect",
"/dashboard/admin-users/page": "/dashboard/admin-users",
"/dashboard/audit-logs/page": "/dashboard/audit-logs",
"/dashboard/billing/page": "/dashboard/billing",
"/dashboard/companies/[id]/page": "/dashboard/companies/[id]",
"/dashboard/companies/page": "/dashboard/companies",
"/dashboard/containers/page": "/dashboard/containers",
"/dashboard/menu-management/page": "/dashboard/menu-management",
"/dashboard/notifications/page": "/dashboard/notifications",
"/dashboard/page": "/dashboard",
"/dashboard/pricing/page": "/dashboard/pricing",
"/dashboard/renters/page": "/dashboard/renters",
"/dashboard/site-config/page": "/dashboard/site-config",
"/favicon.ico/route": "/favicon.ico",
"/forgot-password/page": "/forgot-password",
"/icon/route": "/icon",
"/login/page": "/login",
"/page": "/",
"/reset-password/page": "/reset-password"
}
+21
View File
@@ -0,0 +1,21 @@
{
"pages": {
"/_app": []
},
"devFiles": [],
"polyfillFiles": [
"static/chunks/0cz1d0mv5g_q7.js"
],
"lowPriorityFiles": [
"static/jRlQg50qYlv2hlr5AFzlp/_buildManifest.js",
"static/jRlQg50qYlv2hlr5AFzlp/_ssgManifest.js",
"static/jRlQg50qYlv2hlr5AFzlp/_clientMiddlewareManifest.js"
],
"rootMainFiles": [
"static/chunks/3fi7ta8l6_q46.js",
"static/chunks/2de_cmw_l_puw.js",
"static/chunks/3svce10uq2e6q.js",
"static/chunks/40z7xw1jd_fv0.js",
"static/chunks/turbopack-1kvzti-0-yxfi.js"
]
}
@@ -0,0 +1,6 @@
var R=require("./chunks/[turbopack]_runtime.js")("1af38f23a0b57e90.js")
R.c("chunks/[turbopack-node]_transforms_postcss_ts_1qskksv._.js")
R.c("chunks/[root-of-the-server]__1hypy_2._.js")
R.m("[turbopack-node]/child_process/globals.ts [postcss] (ecmascript)")
R.m("[turbopack-node]/child_process/evaluate.ts/evaluate.js { INNER => \"[turbopack-node]/transforms/postcss.ts { CONFIG => \\\"[project]/apps/admin/postcss.config.js_.loader.mjs [postcss] (ecmascript)\\\" } [postcss] (ecmascript)\", RUNTIME => \"[turbopack-node]/child_process/evaluate.ts [postcss] (ecmascript)\" } [postcss] (ecmascript)")
module.exports=R.m("[turbopack-node]/child_process/evaluate.ts/evaluate.js { INNER => \"[turbopack-node]/transforms/postcss.ts { CONFIG => \\\"[project]/apps/admin/postcss.config.js_.loader.mjs [postcss] (ecmascript)\\\" } [postcss] (ecmascript)\", RUNTIME => \"[turbopack-node]/child_process/evaluate.ts [postcss] (ecmascript)\" } [postcss] (ecmascript)").exports
@@ -0,0 +1,5 @@
{
"version": 3,
"sources": [],
"sections": []
}
@@ -0,0 +1,233 @@
module.exports = [
"[externals]/path [external] (path, cjs)", ((__turbopack_context__, module, exports) => {
const mod = __turbopack_context__.x("path", () => require("path"));
module.exports = mod;
}),
"[externals]/url [external] (url, cjs)", ((__turbopack_context__, module, exports) => {
const mod = __turbopack_context__.x("url", () => require("url"));
module.exports = mod;
}),
"[externals]/fs [external] (fs, cjs)", ((__turbopack_context__, module, exports) => {
const mod = __turbopack_context__.x("fs", () => require("fs"));
module.exports = mod;
}),
"[externals]/node:url [external] (node:url, cjs)", ((__turbopack_context__, module, exports) => {
const mod = __turbopack_context__.x("node:url", () => require("node:url"));
module.exports = mod;
}),
"[externals]/node:path [external] (node:path, cjs)", ((__turbopack_context__, module, exports) => {
const mod = __turbopack_context__.x("node:path", () => require("node:path"));
module.exports = mod;
}),
"[project]/apps/admin/postcss.config.js_.loader.mjs [postcss] (ecmascript)", ((__turbopack_context__) => {
"use strict";
return __turbopack_context__.a(async (__turbopack_handle_async_dependencies__, __turbopack_async_result__) => { try {
__turbopack_context__.s([
"default",
()=>__TURBOPACK__default__export__
]);
var __TURBOPACK__imported__module__$5b$externals$5d2f$node$3a$url__$5b$external$5d$__$28$node$3a$url$2c$__cjs$29$__ = __turbopack_context__.i("[externals]/node:url [external] (node:url, cjs)");
var __TURBOPACK__imported__module__$5b$externals$5d2f$node$3a$path__$5b$external$5d$__$28$node$3a$path$2c$__cjs$29$__ = __turbopack_context__.i("[externals]/node:path [external] (node:path, cjs)");
;
;
const configPath = __TURBOPACK__imported__module__$5b$externals$5d2f$node$3a$path__$5b$external$5d$__$28$node$3a$path$2c$__cjs$29$__["default"].join(process.cwd(), "./postcss.config.js");
// Absolute paths don't work with ESM imports on Windows:
// https://github.com/nodejs/node/issues/31710
// convert it to a file:// URL, which works on all platforms
const configUrl = (0, __TURBOPACK__imported__module__$5b$externals$5d2f$node$3a$url__$5b$external$5d$__$28$node$3a$url$2c$__cjs$29$__["pathToFileURL"])(configPath).toString();
const mod = await __turbopack_context__.y(configUrl);
const __TURBOPACK__default__export__ = mod.default ?? mod;
__turbopack_async_result__();
} catch(e) { __turbopack_async_result__(e); } }, true);}),
"[turbopack-node]/transforms/transforms.ts [postcss] (ecmascript)", ((__turbopack_context__) => {
"use strict";
/**
* Shared utilities for our 2 transform implementations.
*/ __turbopack_context__.s([
"fromPath",
()=>fromPath,
"getReadEnvVariables",
()=>getReadEnvVariables,
"toPath",
()=>toPath
]);
var __TURBOPACK__imported__module__$5b$externals$5d2f$path__$5b$external$5d$__$28$path$2c$__cjs$29$__ = __turbopack_context__.i("[externals]/path [external] (path, cjs)");
;
const contextDir = process.cwd();
const toPath = (file)=>{
const relPath = (0, __TURBOPACK__imported__module__$5b$externals$5d2f$path__$5b$external$5d$__$28$path$2c$__cjs$29$__["relative"])(contextDir, file);
if ((0, __TURBOPACK__imported__module__$5b$externals$5d2f$path__$5b$external$5d$__$28$path$2c$__cjs$29$__["isAbsolute"])(relPath)) {
throw new Error(`Cannot depend on path (${file}) outside of root directory (${contextDir})`);
}
return __TURBOPACK__imported__module__$5b$externals$5d2f$path__$5b$external$5d$__$28$path$2c$__cjs$29$__["sep"] !== '/' ? relPath.replaceAll(__TURBOPACK__imported__module__$5b$externals$5d2f$path__$5b$external$5d$__$28$path$2c$__cjs$29$__["sep"], '/') : relPath;
};
const fromPath = (path)=>{
return (0, __TURBOPACK__imported__module__$5b$externals$5d2f$path__$5b$external$5d$__$28$path$2c$__cjs$29$__["join"])(/* turbopackIgnore: true */ contextDir, __TURBOPACK__imported__module__$5b$externals$5d2f$path__$5b$external$5d$__$28$path$2c$__cjs$29$__["sep"] !== '/' ? path.replaceAll('/', __TURBOPACK__imported__module__$5b$externals$5d2f$path__$5b$external$5d$__$28$path$2c$__cjs$29$__["sep"]) : path);
};
// Patch process.env to track which env vars are read
const originalEnv = process.env;
const readEnvVars = new Set();
process.env = new Proxy(originalEnv, {
get (target, prop) {
if (typeof prop === 'string') {
// We register the env var as dependency on the
// current transform and all future transforms
// since the env var might be cached in module scope
// and influence them all
readEnvVars.add(prop);
}
return Reflect.get(target, prop);
},
set (target, prop, value) {
return Reflect.set(target, prop, value);
}
});
function getReadEnvVariables() {
return Array.from(readEnvVars);
}
}),
"[turbopack-node]/transforms/postcss.ts { CONFIG => \"[project]/apps/admin/postcss.config.js_.loader.mjs [postcss] (ecmascript)\" } [postcss] (ecmascript)", ((__turbopack_context__) => {
"use strict";
return __turbopack_context__.a(async (__turbopack_handle_async_dependencies__, __turbopack_async_result__) => { try {
__turbopack_context__.s([
"default",
()=>transform,
"init",
()=>init
]);
// @ts-ignore
var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$postcss$2f$lib$2f$postcss$2e$mjs__$5b$postcss$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/node_modules/postcss/lib/postcss.mjs [postcss] (ecmascript)");
// @ts-ignore
var __TURBOPACK__imported__module__$5b$project$5d2f$apps$2f$admin$2f$postcss$2e$config$2e$js_$2e$loader$2e$mjs__$5b$postcss$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/apps/admin/postcss.config.js_.loader.mjs [postcss] (ecmascript)");
var __TURBOPACK__imported__module__$5b$turbopack$2d$node$5d2f$transforms$2f$transforms$2e$ts__$5b$postcss$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[turbopack-node]/transforms/transforms.ts [postcss] (ecmascript)");
var __turbopack_async_dependencies__ = __turbopack_handle_async_dependencies__([
__TURBOPACK__imported__module__$5b$project$5d2f$apps$2f$admin$2f$postcss$2e$config$2e$js_$2e$loader$2e$mjs__$5b$postcss$5d$__$28$ecmascript$29$__
]);
[__TURBOPACK__imported__module__$5b$project$5d2f$apps$2f$admin$2f$postcss$2e$config$2e$js_$2e$loader$2e$mjs__$5b$postcss$5d$__$28$ecmascript$29$__] = __turbopack_async_dependencies__.then ? (await __turbopack_async_dependencies__)() : __turbopack_async_dependencies__;
;
;
;
let processor;
const init = async (ipc)=>{
let config = __TURBOPACK__imported__module__$5b$project$5d2f$apps$2f$admin$2f$postcss$2e$config$2e$js_$2e$loader$2e$mjs__$5b$postcss$5d$__$28$ecmascript$29$__["default"];
if (typeof config === 'function') {
config = await config({
env: 'development'
});
}
if (typeof config === 'undefined') {
throw new Error('PostCSS config is undefined (make sure to export an function or object from config file)');
}
let plugins;
if (Array.isArray(config.plugins)) {
plugins = config.plugins.map((plugin)=>{
if (Array.isArray(plugin)) {
return plugin;
} else if (typeof plugin === 'string') {
return [
plugin,
{}
];
} else {
return plugin;
}
});
} else if (typeof config.plugins === 'object') {
plugins = Object.entries(config.plugins).filter(([, options])=>options);
} else {
plugins = [];
}
const loadedPlugins = plugins.map((plugin)=>{
if (Array.isArray(plugin)) {
const [arg, options] = plugin;
let pluginFactory = arg;
if (typeof pluginFactory === 'string') {
pluginFactory = require(/* turbopackIgnore: true */ pluginFactory);
}
if (pluginFactory.default) {
pluginFactory = pluginFactory.default;
}
return pluginFactory(options);
}
return plugin;
});
processor = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$postcss$2f$lib$2f$postcss$2e$mjs__$5b$postcss$5d$__$28$ecmascript$29$__["default"])(loadedPlugins);
};
async function transform(ipc, cssContent, name, sourceMap) {
const { css, map, messages } = await processor.process(cssContent, {
from: name,
to: name,
map: sourceMap ? {
inline: false,
annotation: false
} : undefined
});
const assets = [];
const filePaths = [];
const buildFilePaths = [];
const directories = [];
for (const msg of messages){
switch(msg.type){
case 'asset':
assets.push({
file: msg.file,
content: msg.content,
sourceMap: !sourceMap ? undefined : typeof msg.sourceMap === 'string' ? msg.sourceMap : JSON.stringify(msg.sourceMap)
});
break;
case 'dependency':
case 'missing-dependency':
filePaths.push((0, __TURBOPACK__imported__module__$5b$turbopack$2d$node$5d2f$transforms$2f$transforms$2e$ts__$5b$postcss$5d$__$28$ecmascript$29$__["toPath"])(msg.file));
break;
case 'build-dependency':
buildFilePaths.push((0, __TURBOPACK__imported__module__$5b$turbopack$2d$node$5d2f$transforms$2f$transforms$2e$ts__$5b$postcss$5d$__$28$ecmascript$29$__["toPath"])(msg.file));
break;
case 'dir-dependency':
directories.push([
(0, __TURBOPACK__imported__module__$5b$turbopack$2d$node$5d2f$transforms$2f$transforms$2e$ts__$5b$postcss$5d$__$28$ecmascript$29$__["toPath"])(msg.dir),
msg.glob
]);
break;
case 'context-dependency':
directories.push([
(0, __TURBOPACK__imported__module__$5b$turbopack$2d$node$5d2f$transforms$2f$transforms$2e$ts__$5b$postcss$5d$__$28$ecmascript$29$__["toPath"])(msg.dir),
'**'
]);
break;
default:
break;
}
}
ipc.sendInfo({
type: 'dependencies',
filePaths,
directories,
buildFilePaths,
envVariables: (0, __TURBOPACK__imported__module__$5b$turbopack$2d$node$5d2f$transforms$2f$transforms$2e$ts__$5b$postcss$5d$__$28$ecmascript$29$__["getReadEnvVariables"])()
});
return {
css,
map: sourceMap ? JSON.stringify(map) : undefined,
assets
};
}
__turbopack_async_result__();
} catch(e) { __turbopack_async_result__(e); } }, false);}),
];
//# sourceMappingURL=%5Broot-of-the-server%5D__0g29496._.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,500 @@
module.exports = [
"[turbopack-node]/child_process/globals.ts [postcss] (ecmascript)", ((__turbopack_context__, module, exports) => {
// @ts-ignore
process.turbopack = {};
}),
"[externals]/node:net [external] (node:net, cjs)", ((__turbopack_context__, module, exports) => {
const mod = __turbopack_context__.x("node:net", () => require("node:net"));
module.exports = mod;
}),
"[externals]/node:stream [external] (node:stream, cjs)", ((__turbopack_context__, module, exports) => {
const mod = __turbopack_context__.x("node:stream", () => require("node:stream"));
module.exports = mod;
}),
"[turbopack-node]/compiled/stacktrace-parser/index.js [postcss] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"parse",
()=>parse
]);
if (typeof __nccwpck_require__ !== "undefined") __nccwpck_require__.ab = ("TURBOPACK compile-time value", "/ROOT/compiled/stacktrace-parser") + "/";
var n = "<unknown>";
function parse(e) {
var r = e.split("\n");
return r.reduce(function(e, r) {
var n = parseChrome(r) || parseWinjs(r) || parseGecko(r) || parseNode(r) || parseJSC(r);
if (n) {
e.push(n);
}
return e;
}, []);
}
var a = /^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|\/|[a-z]:\\|\\\\).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
var l = /\((\S*)(?::(\d+))(?::(\d+))\)/;
function parseChrome(e) {
var r = a.exec(e);
if (!r) {
return null;
}
var u = r[2] && r[2].indexOf("native") === 0;
var t = r[2] && r[2].indexOf("eval") === 0;
var i = l.exec(r[2]);
if (t && i != null) {
r[2] = i[1];
r[3] = i[2];
r[4] = i[3];
}
return {
file: !u ? r[2] : null,
methodName: r[1] || n,
arguments: u ? [
r[2]
] : [],
lineNumber: r[3] ? +r[3] : null,
column: r[4] ? +r[4] : null
};
}
var u = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
function parseWinjs(e) {
var r = u.exec(e);
if (!r) {
return null;
}
return {
file: r[2],
methodName: r[1] || n,
arguments: [],
lineNumber: +r[3],
column: r[4] ? +r[4] : null
};
}
var t = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i;
var i = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
function parseGecko(e) {
var r = t.exec(e);
if (!r) {
return null;
}
var a = r[3] && r[3].indexOf(" > eval") > -1;
var l = i.exec(r[3]);
if (a && l != null) {
r[3] = l[1];
r[4] = l[2];
r[5] = null;
}
return {
file: r[3],
methodName: r[1] || n,
arguments: r[2] ? r[2].split(",") : [],
lineNumber: r[4] ? +r[4] : null,
column: r[5] ? +r[5] : null
};
}
var s = /^\s*(?:([^@]*)(?:\((.*?)\))?@)?(\S.*?):(\d+)(?::(\d+))?\s*$/i;
function parseJSC(e) {
var r = s.exec(e);
if (!r) {
return null;
}
return {
file: r[3],
methodName: r[1] || n,
arguments: [],
lineNumber: +r[4],
column: r[5] ? +r[5] : null
};
}
var o = /^\s*at (?:((?:\[object object\])?[^\\/]+(?: \[as \S+\])?) )?\(?(.*?):(\d+)(?::(\d+))?\)?\s*$/i;
function parseNode(e) {
var r = o.exec(e);
if (!r) {
return null;
}
return {
file: r[2],
methodName: r[1] || n,
arguments: [],
lineNumber: +r[3],
column: r[4] ? +r[4] : null
};
}
}),
"[turbopack-node]/error.ts [postcss] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"default",
()=>isError,
"getProperError",
()=>getProperError,
"structuredError",
()=>structuredError
]);
var __TURBOPACK__imported__module__$5b$turbopack$2d$node$5d2f$compiled$2f$stacktrace$2d$parser$2f$index$2e$js__$5b$postcss$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[turbopack-node]/compiled/stacktrace-parser/index.js [postcss] (ecmascript)");
;
function isError(err) {
return typeof err === 'object' && err !== null && 'name' in err && 'message' in err;
}
function getProperError(err) {
if (isError(err)) {
return err;
}
if ("TURBOPACK compile-time falsy", 0) //TURBOPACK unreachable
;
return new Error(isPlainObject(err) ? JSON.stringify(err) : err + '');
}
function getObjectClassLabel(value) {
return Object.prototype.toString.call(value);
}
function isPlainObject(value) {
if (getObjectClassLabel(value) !== '[object Object]') {
return false;
}
const prototype = Object.getPrototypeOf(value);
/**
* this used to be previously:
*
* `return prototype === null || prototype === Object.prototype`
*
* but Edge Runtime expose Object from vm, being that kind of type-checking wrongly fail.
*
* It was changed to the current implementation since it's resilient to serialization.
*/ return prototype === null || prototype.hasOwnProperty('isPrototypeOf');
}
function structuredError(e) {
e = getProperError(e);
return {
name: e.name,
message: e.message,
stack: typeof e.stack === 'string' ? (0, __TURBOPACK__imported__module__$5b$turbopack$2d$node$5d2f$compiled$2f$stacktrace$2d$parser$2f$index$2e$js__$5b$postcss$5d$__$28$ecmascript$29$__["parse"])(e.stack) : [],
cause: e.cause ? structuredError(getProperError(e.cause)) : undefined
};
}
}),
"[turbopack-node]/child_process/index.ts [postcss] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"IPC",
()=>IPC
]);
var __TURBOPACK__imported__module__$5b$externals$5d2f$node$3a$net__$5b$external$5d$__$28$node$3a$net$2c$__cjs$29$__ = __turbopack_context__.i("[externals]/node:net [external] (node:net, cjs)");
var __TURBOPACK__imported__module__$5b$externals$5d2f$node$3a$stream__$5b$external$5d$__$28$node$3a$stream$2c$__cjs$29$__ = __turbopack_context__.i("[externals]/node:stream [external] (node:stream, cjs)");
var __TURBOPACK__imported__module__$5b$turbopack$2d$node$5d2f$error$2e$ts__$5b$postcss$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[turbopack-node]/error.ts [postcss] (ecmascript)");
;
;
;
function createIpc(port) {
const socket = (0, __TURBOPACK__imported__module__$5b$externals$5d2f$node$3a$net__$5b$external$5d$__$28$node$3a$net$2c$__cjs$29$__["createConnection"])({
port,
host: '127.0.0.1'
});
/**
* A writable stream that writes to the socket.
* We don't write directly to the socket because we need to
* handle backpressure and wait for the socket to be drained
* before writing more data.
*/ const socketWritable = new __TURBOPACK__imported__module__$5b$externals$5d2f$node$3a$stream__$5b$external$5d$__$28$node$3a$stream$2c$__cjs$29$__["Writable"]({
write (chunk, _enc, cb) {
if (socket.write(chunk)) {
cb();
} else {
socket.once('drain', cb);
}
},
final (cb) {
socket.end(cb);
}
});
const packetQueue = [];
const recvPromiseResolveQueue = [];
function pushPacket(packet) {
const recvPromiseResolve = recvPromiseResolveQueue.shift();
if (recvPromiseResolve != null) {
recvPromiseResolve(JSON.parse(packet.toString('utf8')));
} else {
packetQueue.push(packet);
}
}
let state = {
type: 'waiting'
};
let buffer = Buffer.alloc(0);
socket.once('connect', ()=>{
socket.setNoDelay(true);
socket.on('data', (chunk)=>{
buffer = Buffer.concat([
buffer,
chunk
]);
loop: while(true){
switch(state.type){
case 'waiting':
{
if (buffer.length >= 4) {
const length = buffer.readUInt32BE(0);
buffer = buffer.subarray(4);
state = {
type: 'packet',
length
};
} else {
break loop;
}
break;
}
case 'packet':
{
if (buffer.length >= state.length) {
const packet = buffer.subarray(0, state.length);
buffer = buffer.subarray(state.length);
state = {
type: 'waiting'
};
pushPacket(packet);
} else {
break loop;
}
break;
}
default:
invariant(state, (state)=>`Unknown state type: ${state?.type}`);
}
}
});
});
// When the socket is closed, this process is no longer needed.
// This might happen e. g. when parent process is killed or
// node.js pool is garbage collected.
socket.once('close', ()=>{
process.exit(0);
});
// TODO(lukesandberg): some of the messages being sent are very large and contain lots
// of redundant information. Consider adding gzip compression to our stream.
function doSend(message) {
return new Promise((resolve, reject)=>{
// Reserve 4 bytes for our length prefix, we will over-write after encoding.
const packet = Buffer.from('0000' + message, 'utf8');
packet.writeUInt32BE(packet.length - 4, 0);
socketWritable.write(packet, (err)=>{
process.stderr.write(`TURBOPACK_OUTPUT_D\n`);
process.stdout.write(`TURBOPACK_OUTPUT_D\n`);
if (err != null) {
reject(err);
} else {
resolve();
}
});
});
}
function send(message) {
return doSend(JSON.stringify(message));
}
function sendReady() {
return doSend('');
}
return {
async recv () {
const packet = packetQueue.shift();
if (packet != null) {
return JSON.parse(packet.toString('utf8'));
}
const result = await new Promise((resolve)=>{
recvPromiseResolveQueue.push((result)=>{
resolve(result);
});
});
return result;
},
send (message) {
return send(message);
},
sendReady,
async sendError (error) {
let failed = false;
try {
await send({
type: 'error',
...(0, __TURBOPACK__imported__module__$5b$turbopack$2d$node$5d2f$error$2e$ts__$5b$postcss$5d$__$28$ecmascript$29$__["structuredError"])(error)
});
} catch (err) {
// There's nothing we can do about errors that happen after this point, we can't tell anyone
// about them.
console.error('failed to send error back to rust:', err);
failed = true;
}
await new Promise((res)=>socket.end(()=>res()));
process.exit(failed ? 1 : 0);
}
};
}
const PORT = process.argv[2];
const IPC = createIpc(parseInt(PORT, 10));
process.on('uncaughtException', (err)=>{
IPC.sendError(err);
});
process.on('unhandledRejection', (reason)=>{
IPC.sendError(reason instanceof Error ? reason : new Error(String(reason)));
});
const improveConsole = (name, stream, addStack)=>{
// @ts-ignore
const original = console[name];
// @ts-ignore
const stdio = process[stream];
// @ts-ignore
console[name] = (...args)=>{
stdio.write(`TURBOPACK_OUTPUT_B\n`);
original(...args);
if (addStack) {
const stack = new Error().stack?.replace(/^.+\n.+\n/, '') + '\n';
stdio.write('TURBOPACK_OUTPUT_S\n');
stdio.write(stack);
}
stdio.write('TURBOPACK_OUTPUT_E\n');
};
};
improveConsole('error', 'stderr', true);
improveConsole('warn', 'stderr', true);
improveConsole('count', 'stdout', true);
improveConsole('trace', 'stderr', false);
improveConsole('log', 'stdout', true);
improveConsole('group', 'stdout', true);
improveConsole('groupCollapsed', 'stdout', true);
improveConsole('table', 'stdout', true);
improveConsole('debug', 'stdout', true);
improveConsole('info', 'stdout', true);
improveConsole('dir', 'stdout', true);
improveConsole('dirxml', 'stdout', true);
improveConsole('timeEnd', 'stdout', true);
improveConsole('timeLog', 'stdout', true);
improveConsole('timeStamp', 'stdout', true);
improveConsole('assert', 'stderr', true);
/**
* Utility function to ensure all variants of an enum are handled.
*/ function invariant(never, computeMessage) {
throw new Error(`Invariant: ${computeMessage(never)}`);
}
}),
"[turbopack-node]/child_process/evaluate.ts [postcss] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"run",
()=>run
]);
var __TURBOPACK__imported__module__$5b$turbopack$2d$node$5d2f$child_process$2f$index$2e$ts__$5b$postcss$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[turbopack-node]/child_process/index.ts [postcss] (ecmascript)");
;
const ipc = __TURBOPACK__imported__module__$5b$turbopack$2d$node$5d2f$child_process$2f$index$2e$ts__$5b$postcss$5d$__$28$ecmascript$29$__["IPC"];
const queue = [];
const run = async (moduleFactory)=>{
let nextId = 1;
const requests = new Map();
const internalIpc = {
sendInfo: (message)=>ipc.send({
type: 'info',
data: message
}),
sendRequest: (message)=>{
const id = nextId++;
let resolve, reject;
const promise = new Promise((res, rej)=>{
resolve = res;
reject = rej;
});
requests.set(id, {
resolve,
reject
});
return ipc.send({
type: 'request',
id,
data: message
}).then(()=>promise);
},
sendError: (error)=>{
return ipc.sendError(error);
}
};
// Initialize module and send ready message
let getValue;
try {
const module = await moduleFactory();
if (typeof module.init === 'function') {
await module.init();
}
getValue = module.default;
await ipc.sendReady();
} catch (err) {
await ipc.sendReady();
await ipc.sendError(err);
}
// Queue handling
let isRunning = false;
const run = async ()=>{
while(queue.length > 0){
const args = queue.shift();
try {
const value = await getValue(internalIpc, ...args);
await ipc.send({
type: 'end',
data: value === undefined ? undefined : JSON.stringify(value, null, 2),
duration: 0
});
} catch (e) {
await ipc.sendError(e);
}
}
isRunning = false;
};
// Communication handling
while(true){
const msg = await ipc.recv();
switch(msg.type){
case 'evaluate':
{
queue.push(msg.args);
if (!isRunning) {
isRunning = true;
run();
}
break;
}
case 'result':
{
const request = requests.get(msg.id);
if (request) {
requests.delete(msg.id);
if (msg.error) {
request.reject(new Error(msg.error));
} else {
request.resolve(msg.data);
}
}
break;
}
default:
{
console.error('unexpected message type', msg.type);
process.exit(1);
}
}
}
};
}),
"[turbopack-node]/child_process/evaluate.ts/evaluate.js { INNER => \"[turbopack-node]/transforms/postcss.ts { CONFIG => \\\"[project]/apps/admin/postcss.config.js_.loader.mjs [postcss] (ecmascript)\\\" } [postcss] (ecmascript)\", RUNTIME => \"[turbopack-node]/child_process/evaluate.ts [postcss] (ecmascript)\" } [postcss] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([]);
var __TURBOPACK__imported__module__$5b$turbopack$2d$node$5d2f$child_process$2f$evaluate$2e$ts__$5b$postcss$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[turbopack-node]/child_process/evaluate.ts [postcss] (ecmascript)");
;
(0, __TURBOPACK__imported__module__$5b$turbopack$2d$node$5d2f$child_process$2f$evaluate$2e$ts__$5b$postcss$5d$__$28$ecmascript$29$__["run"])(()=>__turbopack_context__.A('[turbopack-node]/transforms/postcss.ts { CONFIG => "[project]/apps/admin/postcss.config.js_.loader.mjs [postcss] (ecmascript)" } [postcss] (ecmascript, async loader)'));
}),
];
//# sourceMappingURL=%5Broot-of-the-server%5D__1hypy_2._.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,13 @@
module.exports = [
"[turbopack-node]/transforms/postcss.ts { CONFIG => \"[project]/apps/admin/postcss.config.js_.loader.mjs [postcss] (ecmascript)\" } [postcss] (ecmascript, async loader)", ((__turbopack_context__) => {
__turbopack_context__.v((parentImport) => {
return Promise.all([
"chunks/node_modules_20v-8wl._.js",
"chunks/[root-of-the-server]__0g29496._.js"
].map((chunk) => __turbopack_context__.l(chunk))).then(() => {
return parentImport("[turbopack-node]/transforms/postcss.ts { CONFIG => \"[project]/apps/admin/postcss.config.js_.loader.mjs [postcss] (ecmascript)\" } [postcss] (ecmascript)");
});
});
}),
];
@@ -0,0 +1,5 @@
{
"version": 3,
"sources": [],
"sections": []
}
@@ -0,0 +1,890 @@
const RUNTIME_PUBLIC_PATH = "chunks/[turbopack]_runtime.js";
const RELATIVE_ROOT_PATH = "../../..";
const ASSET_PREFIX = "/";
const WORKER_FORWARDED_GLOBALS = [];
/**
* This file contains runtime types and functions that are shared between all
* TurboPack ECMAScript runtimes.
*
* It will be prepended to the runtime code of each runtime.
*/ /* eslint-disable @typescript-eslint/no-unused-vars */ /// <reference path="./runtime-types.d.ts" />
/**
* Describes why a module was instantiated.
* Shared between browser and Node.js runtimes.
*/ var SourceType = /*#__PURE__*/ function(SourceType) {
/**
* The module was instantiated because it was included in an evaluated chunk's
* runtime.
* SourceData is a ChunkPath.
*/ SourceType[SourceType["Runtime"] = 0] = "Runtime";
/**
* The module was instantiated because a parent module imported it.
* SourceData is a ModuleId.
*/ SourceType[SourceType["Parent"] = 1] = "Parent";
/**
* The module was instantiated because it was included in a chunk's hot module
* update.
* SourceData is an array of ModuleIds or undefined.
*/ SourceType[SourceType["Update"] = 2] = "Update";
return SourceType;
}(SourceType || {});
/**
* Flag indicating which module object type to create when a module is merged. Set to `true`
* by each runtime that uses ModuleWithDirection (browser dev-base.ts, nodejs dev-base.ts,
* nodejs build-base.ts). Browser production (build-base.ts) leaves it as `false` since it
* uses plain Module objects.
*/ let createModuleWithDirectionFlag = false;
const REEXPORTED_OBJECTS = new WeakMap();
/**
* Constructs the `__turbopack_context__` object for a module.
*/ function Context(module, exports) {
this.m = module;
// We need to store this here instead of accessing it from the module object to:
// 1. Make it available to factories directly, since we rewrite `this` to
// `__turbopack_context__.e` in CJS modules.
// 2. Support async modules which rewrite `module.exports` to a promise, so we
// can still access the original exports object from functions like
// `esmExport`
// Ideally we could find a new approach for async modules and drop this property altogether.
this.e = exports;
}
const contextPrototype = Context.prototype;
const hasOwnProperty = Object.prototype.hasOwnProperty;
const toStringTag = typeof Symbol !== 'undefined' && Symbol.toStringTag;
function defineProp(obj, name, options) {
if (!hasOwnProperty.call(obj, name)) Object.defineProperty(obj, name, options);
}
function getOverwrittenModule(moduleCache, id) {
let module = moduleCache[id];
if (!module) {
if (createModuleWithDirectionFlag) {
// set in development modes for hmr support
module = createModuleWithDirection(id);
} else {
module = createModuleObject(id);
}
moduleCache[id] = module;
}
return module;
}
/**
* Creates the module object. Only done here to ensure all module objects have the same shape.
*/ function createModuleObject(id) {
return {
exports: {},
error: undefined,
id,
namespaceObject: undefined
};
}
function createModuleWithDirection(id) {
return {
exports: {},
error: undefined,
id,
namespaceObject: undefined,
parents: [],
children: []
};
}
const BindingTag_Value = 0;
/**
* Adds the getters to the exports object.
*/ function esm(exports, bindings) {
defineProp(exports, '__esModule', {
value: true
});
if (toStringTag) defineProp(exports, toStringTag, {
value: 'Module'
});
let i = 0;
while(i < bindings.length){
const propName = bindings[i++];
const tagOrFunction = bindings[i++];
if (typeof tagOrFunction === 'number') {
if (tagOrFunction === BindingTag_Value) {
defineProp(exports, propName, {
value: bindings[i++],
enumerable: true,
writable: false
});
} else {
throw new Error(`unexpected tag: ${tagOrFunction}`);
}
} else {
const getterFn = tagOrFunction;
if (typeof bindings[i] === 'function') {
const setterFn = bindings[i++];
defineProp(exports, propName, {
get: getterFn,
set: setterFn,
enumerable: true
});
} else {
defineProp(exports, propName, {
get: getterFn,
enumerable: true
});
}
}
}
Object.seal(exports);
}
/**
* Makes the module an ESM with exports
*/ function esmExport(bindings, id) {
let module;
let exports;
if (id != null) {
module = getOverwrittenModule(this.c, id);
exports = module.exports;
} else {
module = this.m;
exports = this.e;
}
module.namespaceObject = exports;
esm(exports, bindings);
}
contextPrototype.s = esmExport;
function ensureDynamicExports(module, exports) {
let reexportedObjects = REEXPORTED_OBJECTS.get(module);
if (!reexportedObjects) {
REEXPORTED_OBJECTS.set(module, reexportedObjects = []);
module.exports = module.namespaceObject = new Proxy(exports, {
get (target, prop) {
if (hasOwnProperty.call(target, prop) || prop === 'default' || prop === '__esModule') {
return Reflect.get(target, prop);
}
for (const obj of reexportedObjects){
const value = Reflect.get(obj, prop);
if (value !== undefined) return value;
}
return undefined;
},
ownKeys (target) {
const keys = Reflect.ownKeys(target);
for (const obj of reexportedObjects){
for (const key of Reflect.ownKeys(obj)){
if (key !== 'default' && !keys.includes(key)) keys.push(key);
}
}
return keys;
}
});
}
return reexportedObjects;
}
/**
* Dynamically exports properties from an object
*/ function dynamicExport(object, id) {
let module;
let exports;
if (id != null) {
module = getOverwrittenModule(this.c, id);
exports = module.exports;
} else {
module = this.m;
exports = this.e;
}
const reexportedObjects = ensureDynamicExports(module, exports);
if (typeof object === 'object' && object !== null) {
reexportedObjects.push(object);
}
}
contextPrototype.j = dynamicExport;
function exportValue(value, id) {
let module;
if (id != null) {
module = getOverwrittenModule(this.c, id);
} else {
module = this.m;
}
module.exports = value;
}
contextPrototype.v = exportValue;
function exportNamespace(namespace, id) {
let module;
if (id != null) {
module = getOverwrittenModule(this.c, id);
} else {
module = this.m;
}
module.exports = module.namespaceObject = namespace;
}
contextPrototype.n = exportNamespace;
function createGetter(obj, key) {
return ()=>obj[key];
}
/**
* @returns prototype of the object
*/ const getProto = Object.getPrototypeOf ? (obj)=>Object.getPrototypeOf(obj) : (obj)=>obj.__proto__;
/** Prototypes that are not expanded for exports */ const LEAF_PROTOTYPES = [
null,
getProto({}),
getProto([]),
getProto(getProto)
];
/**
* @param raw
* @param ns
* @param allowExportDefault
* * `false`: will have the raw module as default export
* * `true`: will have the default property as default export
*/ function interopEsm(raw, ns, allowExportDefault) {
const bindings = [];
let defaultLocation = -1;
for(let current = raw; (typeof current === 'object' || typeof current === 'function') && !LEAF_PROTOTYPES.includes(current); current = getProto(current)){
for (const key of Object.getOwnPropertyNames(current)){
bindings.push(key, createGetter(raw, key));
if (defaultLocation === -1 && key === 'default') {
defaultLocation = bindings.length - 1;
}
}
}
// this is not really correct
// we should set the `default` getter if the imported module is a `.cjs file`
if (!(allowExportDefault && defaultLocation >= 0)) {
// Replace the binding with one for the namespace itself in order to preserve iteration order.
if (defaultLocation >= 0) {
// Replace the getter with the value
bindings.splice(defaultLocation, 1, BindingTag_Value, raw);
} else {
bindings.push('default', BindingTag_Value, raw);
}
}
esm(ns, bindings);
return ns;
}
function createNS(raw) {
if (typeof raw === 'function') {
return function(...args) {
return raw.apply(this, args);
};
} else {
return Object.create(null);
}
}
function esmImport(id) {
const module = getOrInstantiateModuleFromParent(id, this.m);
// any ES module has to have `module.namespaceObject` defined.
if (module.namespaceObject) return module.namespaceObject;
// only ESM can be an async module, so we don't need to worry about exports being a promise here.
const raw = module.exports;
return module.namespaceObject = interopEsm(raw, createNS(raw), raw && raw.__esModule);
}
contextPrototype.i = esmImport;
function asyncLoader(moduleId) {
const loader = this.r(moduleId);
return loader(esmImport.bind(this));
}
contextPrototype.A = asyncLoader;
// Add a simple runtime require so that environments without one can still pass
// `typeof require` CommonJS checks so that exports are correctly registered.
const runtimeRequire = // @ts-ignore
typeof require === 'function' ? require : function require1() {
throw new Error('Unexpected use of runtime require');
};
contextPrototype.t = runtimeRequire;
function commonJsRequire(id) {
return getOrInstantiateModuleFromParent(id, this.m).exports;
}
contextPrototype.r = commonJsRequire;
/**
* Remove fragments and query parameters since they are never part of the context map keys
*
* This matches how we parse patterns at resolving time. Arguably we should only do this for
* strings passed to `import` but the resolve does it for `import` and `require` and so we do
* here as well.
*/ function parseRequest(request) {
// Per the URI spec fragments can contain `?` characters, so we should trim it off first
// https://datatracker.ietf.org/doc/html/rfc3986#section-3.5
const hashIndex = request.indexOf('#');
if (hashIndex !== -1) {
request = request.substring(0, hashIndex);
}
const queryIndex = request.indexOf('?');
if (queryIndex !== -1) {
request = request.substring(0, queryIndex);
}
return request;
}
/**
* `require.context` and require/import expression runtime.
*/ function moduleContext(map) {
function moduleContext(id) {
id = parseRequest(id);
if (hasOwnProperty.call(map, id)) {
return map[id].module();
}
const e = new Error(`Cannot find module '${id}'`);
e.code = 'MODULE_NOT_FOUND';
throw e;
}
moduleContext.keys = ()=>{
return Object.keys(map);
};
moduleContext.resolve = (id)=>{
id = parseRequest(id);
if (hasOwnProperty.call(map, id)) {
return map[id].id();
}
const e = new Error(`Cannot find module '${id}'`);
e.code = 'MODULE_NOT_FOUND';
throw e;
};
moduleContext.import = async (id)=>{
return await moduleContext(id);
};
return moduleContext;
}
contextPrototype.f = moduleContext;
/**
* Returns the path of a chunk defined by its data.
*/ function getChunkPath(chunkData) {
return typeof chunkData === 'string' ? chunkData : chunkData.path;
}
function isPromise(maybePromise) {
return maybePromise != null && typeof maybePromise === 'object' && 'then' in maybePromise && typeof maybePromise.then === 'function';
}
function isAsyncModuleExt(obj) {
return turbopackQueues in obj;
}
function createPromise() {
let resolve;
let reject;
const promise = new Promise((res, rej)=>{
reject = rej;
resolve = res;
});
return {
promise,
resolve: resolve,
reject: reject
};
}
// Load the CompressedmoduleFactories of a chunk into the `moduleFactories` Map.
// The CompressedModuleFactories format is
// - 1 or more module ids
// - a module factory function
// So walking this is a little complex but the flat structure is also fast to
// traverse, we can use `typeof` operators to distinguish the two cases.
function installCompressedModuleFactories(chunkModules, offset, moduleFactories, newModuleId) {
let i = offset;
while(i < chunkModules.length){
let end = i + 1;
// Find our factory function
while(end < chunkModules.length && typeof chunkModules[end] !== 'function'){
end++;
}
if (end === chunkModules.length) {
throw new Error('malformed chunk format, expected a factory function');
}
// Install the factory for each module ID that doesn't already have one.
// When some IDs in this group already have a factory, reuse that existing
// group factory for the missing IDs to keep all IDs in the group consistent.
// Otherwise, install the factory from this chunk.
const moduleFactoryFn = chunkModules[end];
let existingGroupFactory = undefined;
for(let j = i; j < end; j++){
const id = chunkModules[j];
const existingFactory = moduleFactories.get(id);
if (existingFactory) {
existingGroupFactory = existingFactory;
break;
}
}
const factoryToInstall = existingGroupFactory ?? moduleFactoryFn;
let didInstallFactory = false;
for(let j = i; j < end; j++){
const id = chunkModules[j];
if (!moduleFactories.has(id)) {
if (!didInstallFactory) {
if (factoryToInstall === moduleFactoryFn) {
applyModuleFactoryName(moduleFactoryFn);
}
didInstallFactory = true;
}
moduleFactories.set(id, factoryToInstall);
newModuleId?.(id);
}
}
i = end + 1; // end is pointing at the last factory advance to the next id or the end of the array.
}
}
// everything below is adapted from webpack
// https://github.com/webpack/webpack/blob/6be4065ade1e252c1d8dcba4af0f43e32af1bdc1/lib/runtime/AsyncModuleRuntimeModule.js#L13
const turbopackQueues = Symbol('turbopack queues');
const turbopackExports = Symbol('turbopack exports');
const turbopackError = Symbol('turbopack error');
function resolveQueue(queue) {
if (queue && queue.status !== 1) {
queue.status = 1;
queue.forEach((fn)=>fn.queueCount--);
queue.forEach((fn)=>fn.queueCount-- ? fn.queueCount++ : fn());
}
}
function wrapDeps(deps) {
return deps.map((dep)=>{
if (dep !== null && typeof dep === 'object') {
if (isAsyncModuleExt(dep)) return dep;
if (isPromise(dep)) {
const queue = Object.assign([], {
status: 0
});
const obj = {
[turbopackExports]: {},
[turbopackQueues]: (fn)=>fn(queue)
};
dep.then((res)=>{
obj[turbopackExports] = res;
resolveQueue(queue);
}, (err)=>{
obj[turbopackError] = err;
resolveQueue(queue);
});
return obj;
}
}
return {
[turbopackExports]: dep,
[turbopackQueues]: ()=>{}
};
});
}
function asyncModule(body, hasAwait) {
const module = this.m;
const queue = hasAwait ? Object.assign([], {
status: -1
}) : undefined;
const depQueues = new Set();
const { resolve, reject, promise: rawPromise } = createPromise();
const promise = Object.assign(rawPromise, {
[turbopackExports]: module.exports,
[turbopackQueues]: (fn)=>{
queue && fn(queue);
depQueues.forEach(fn);
promise['catch'](()=>{});
}
});
const attributes = {
get () {
return promise;
},
set (v) {
// Calling `esmExport` leads to this.
if (v !== promise) {
promise[turbopackExports] = v;
}
}
};
Object.defineProperty(module, 'exports', attributes);
Object.defineProperty(module, 'namespaceObject', attributes);
function handleAsyncDependencies(deps) {
const currentDeps = wrapDeps(deps);
const getResult = ()=>currentDeps.map((d)=>{
if (d[turbopackError]) throw d[turbopackError];
return d[turbopackExports];
});
const { promise, resolve } = createPromise();
const fn = Object.assign(()=>resolve(getResult), {
queueCount: 0
});
function fnQueue(q) {
if (q !== queue && !depQueues.has(q)) {
depQueues.add(q);
if (q && q.status === 0) {
fn.queueCount++;
q.push(fn);
}
}
}
currentDeps.map((dep)=>dep[turbopackQueues](fnQueue));
return fn.queueCount ? promise : getResult();
}
function asyncResult(err) {
if (err) {
reject(promise[turbopackError] = err);
} else {
resolve(promise[turbopackExports]);
}
resolveQueue(queue);
}
body(handleAsyncDependencies, asyncResult);
if (queue && queue.status === -1) {
queue.status = 0;
}
}
contextPrototype.a = asyncModule;
/**
* A pseudo "fake" URL object to resolve to its relative path.
*
* When UrlRewriteBehavior is set to relative, calls to the `new URL()` will construct url without base using this
* runtime function to generate context-agnostic urls between different rendering context, i.e ssr / client to avoid
* hydration mismatch.
*
* This is based on webpack's existing implementation:
* https://github.com/webpack/webpack/blob/87660921808566ef3b8796f8df61bd79fc026108/lib/runtime/RelativeUrlRuntimeModule.js
*/ const relativeURL = function relativeURL(inputUrl) {
const realUrl = new URL(inputUrl, 'x:/');
const values = {};
for(const key in realUrl)values[key] = realUrl[key];
values.href = inputUrl;
values.pathname = inputUrl.replace(/[?#].*/, '');
values.origin = values.protocol = '';
values.toString = values.toJSON = (..._args)=>inputUrl;
for(const key in values)Object.defineProperty(this, key, {
enumerable: true,
configurable: true,
value: values[key]
});
};
relativeURL.prototype = URL.prototype;
contextPrototype.U = relativeURL;
/**
* Utility function to ensure all variants of an enum are handled.
*/ function invariant(never, computeMessage) {
throw new Error(`Invariant: ${computeMessage(never)}`);
}
/**
* Constructs an error message for when a module factory is not available.
*/ function factoryNotAvailableMessage(moduleId, sourceType, sourceData) {
let instantiationReason;
switch(sourceType){
case 0:
instantiationReason = `as a runtime entry of chunk ${sourceData}`;
break;
case 1:
instantiationReason = `because it was required from module ${sourceData}`;
break;
case 2:
instantiationReason = 'because of an HMR update';
break;
default:
invariant(sourceType, (sourceType)=>`Unknown source type: ${sourceType}`);
}
return `Module ${moduleId} was instantiated ${instantiationReason}, but the module factory is not available.`;
}
/**
* A stub function to make `require` available but non-functional in ESM.
*/ function requireStub(_moduleId) {
throw new Error('dynamic usage of require is not supported');
}
contextPrototype.z = requireStub;
// Make `globalThis` available to the module in a way that cannot be shadowed by a local variable.
contextPrototype.g = globalThis;
function applyModuleFactoryName(factory) {
// Give the module factory a nice name to improve stack traces.
Object.defineProperty(factory, 'name', {
value: 'module evaluation'
});
}
/// <reference path="../shared/runtime/runtime-utils.ts" />
/// A 'base' utilities to support runtime can have externals.
/// Currently this is for node.js / edge runtime both.
/// If a fn requires node.js specific behavior, it should be placed in `node-external-utils` instead.
async function externalImport(id) {
let raw;
try {
raw = await import(id);
} catch (err) {
// TODO(alexkirsz) This can happen when a client-side module tries to load
// an external module we don't provide a shim for (e.g. querystring, url).
// For now, we fail semi-silently, but in the future this should be a
// compilation error.
throw new Error(`Failed to load external module ${id}: ${err}`);
}
if (raw && raw.__esModule && raw.default && 'default' in raw.default) {
return interopEsm(raw.default, createNS(raw), true);
}
return raw;
}
contextPrototype.y = externalImport;
function externalRequire(id, thunk, esm = false) {
let raw;
try {
raw = thunk();
} catch (err) {
// TODO(alexkirsz) This can happen when a client-side module tries to load
// an external module we don't provide a shim for (e.g. querystring, url).
// For now, we fail semi-silently, but in the future this should be a
// compilation error.
throw new Error(`Failed to load external module ${id}: ${err}`);
}
if (!esm || raw.__esModule) {
return raw;
}
return interopEsm(raw, createNS(raw), true);
}
externalRequire.resolve = (id, options)=>{
return require.resolve(id, options);
};
contextPrototype.x = externalRequire;
/* eslint-disable @typescript-eslint/no-unused-vars */ const path = require('path');
const relativePathToRuntimeRoot = path.relative(RUNTIME_PUBLIC_PATH, '.');
// Compute the relative path to the `distDir`.
const relativePathToDistRoot = path.join(relativePathToRuntimeRoot, RELATIVE_ROOT_PATH);
const RUNTIME_ROOT = path.resolve(__filename, relativePathToRuntimeRoot);
// Compute the absolute path to the root, by stripping distDir from the absolute path to this file.
const ABSOLUTE_ROOT = path.resolve(__filename, relativePathToDistRoot);
/**
* Returns an absolute path to the given module path.
* Module path should be relative, either path to a file or a directory.
*
* This fn allows to calculate an absolute path for some global static values, such as
* `__dirname` or `import.meta.url` that Turbopack will not embeds in compile time.
* See ImportMetaBinding::code_generation for the usage.
*/ function resolveAbsolutePath(modulePath) {
if (modulePath) {
return path.join(ABSOLUTE_ROOT, modulePath);
}
return ABSOLUTE_ROOT;
}
Context.prototype.P = resolveAbsolutePath;
/* eslint-disable @typescript-eslint/no-unused-vars */ /// <reference path="../shared/runtime/runtime-utils.ts" />
function readWebAssemblyAsResponse(path) {
const { createReadStream } = require('fs');
const { Readable } = require('stream');
const stream = createReadStream(path);
// @ts-ignore unfortunately there's a slight type mismatch with the stream.
return new Response(Readable.toWeb(stream), {
headers: {
'content-type': 'application/wasm'
}
});
}
async function compileWebAssemblyFromPath(path) {
const response = readWebAssemblyAsResponse(path);
return await WebAssembly.compileStreaming(response);
}
async function instantiateWebAssemblyFromPath(path, importsObj) {
const response = readWebAssemblyAsResponse(path);
const { instance } = await WebAssembly.instantiateStreaming(response, importsObj);
return instance.exports;
}
/* eslint-disable @typescript-eslint/no-unused-vars */ /// <reference path="../../shared/runtime/runtime-utils.ts" />
/// <reference path="../../shared-node/base-externals-utils.ts" />
/// <reference path="../../shared-node/node-externals-utils.ts" />
/// <reference path="../../shared-node/node-wasm-utils.ts" />
/// <reference path="./nodejs-globals.d.ts" />
/**
* Base Node.js runtime shared between production and development.
* Contains chunk loading, module caching, and other non-HMR functionality.
*/ process.env.TURBOPACK = '1';
const url = require('url');
const moduleFactories = new Map();
const moduleCache = Object.create(null);
/**
* Returns an absolute path to the given module's id.
*/ function resolvePathFromModule(moduleId) {
const exported = this.r(moduleId);
const exportedPath = exported?.default ?? exported;
if (typeof exportedPath !== 'string') {
return exported;
}
const strippedAssetPrefix = exportedPath.slice(ASSET_PREFIX.length);
const resolved = path.resolve(RUNTIME_ROOT, strippedAssetPrefix);
return url.pathToFileURL(resolved).href;
}
/**
* Exports a URL value. No suffix is added in Node.js runtime.
*/ function exportUrl(urlValue, id) {
exportValue.call(this, urlValue, id);
}
function loadRuntimeChunk(sourcePath, chunkData) {
if (typeof chunkData === 'string') {
loadRuntimeChunkPath(sourcePath, chunkData);
} else {
loadRuntimeChunkPath(sourcePath, chunkData.path);
}
}
const loadedChunks = new Set();
const unsupportedLoadChunk = Promise.resolve(undefined);
const loadedChunk = Promise.resolve(undefined);
const chunkCache = new Map();
function clearChunkCache() {
chunkCache.clear();
loadedChunks.clear();
}
function loadRuntimeChunkPath(sourcePath, chunkPath) {
if (!isJs(chunkPath)) {
// We only support loading JS chunks in Node.js.
// This branch can be hit when trying to load a CSS chunk.
return;
}
if (loadedChunks.has(chunkPath)) {
return;
}
try {
const resolved = path.resolve(RUNTIME_ROOT, chunkPath);
const chunkModules = require(resolved);
installCompressedModuleFactories(chunkModules, 0, moduleFactories);
loadedChunks.add(chunkPath);
} catch (cause) {
let errorMessage = `Failed to load chunk ${chunkPath}`;
if (sourcePath) {
errorMessage += ` from runtime for chunk ${sourcePath}`;
}
const error = new Error(errorMessage, {
cause
});
error.name = 'ChunkLoadError';
throw error;
}
}
function loadChunkAsync(chunkData) {
const chunkPath = typeof chunkData === 'string' ? chunkData : chunkData.path;
if (!isJs(chunkPath)) {
// We only support loading JS chunks in Node.js.
// This branch can be hit when trying to load a CSS chunk.
return unsupportedLoadChunk;
}
let entry = chunkCache.get(chunkPath);
if (entry === undefined) {
try {
// resolve to an absolute path to simplify `require` handling
const resolved = path.resolve(RUNTIME_ROOT, chunkPath);
// TODO: consider switching to `import()` to enable concurrent chunk loading and async file io
// However this is incompatible with hot reloading (since `import` doesn't use the require cache)
const chunkModules = require(resolved);
installCompressedModuleFactories(chunkModules, 0, moduleFactories);
entry = loadedChunk;
} catch (cause) {
const errorMessage = `Failed to load chunk ${chunkPath} from module ${this.m.id}`;
const error = new Error(errorMessage, {
cause
});
error.name = 'ChunkLoadError';
// Cache the failure promise, future requests will also get this same rejection
entry = Promise.reject(error);
}
chunkCache.set(chunkPath, entry);
}
// TODO: Return an instrumented Promise that React can use instead of relying on referential equality.
return entry;
}
contextPrototype.l = loadChunkAsync;
function loadChunkAsyncByUrl(chunkUrl) {
const path1 = url.fileURLToPath(new URL(chunkUrl, RUNTIME_ROOT));
return loadChunkAsync.call(this, path1);
}
contextPrototype.L = loadChunkAsyncByUrl;
function loadWebAssembly(chunkPath, _edgeModule, imports) {
const resolved = path.resolve(RUNTIME_ROOT, chunkPath);
return instantiateWebAssemblyFromPath(resolved, imports);
}
contextPrototype.w = loadWebAssembly;
function loadWebAssemblyModule(chunkPath, _edgeModule) {
const resolved = path.resolve(RUNTIME_ROOT, chunkPath);
return compileWebAssemblyFromPath(resolved);
}
contextPrototype.u = loadWebAssemblyModule;
/**
* Creates a Node.js worker thread by instantiating the given WorkerConstructor
* with the appropriate path and options, including forwarded globals.
*
* @param WorkerConstructor The Worker constructor from worker_threads
* @param workerPath Path to the worker entry chunk
* @param workerOptions options to pass to the Worker constructor (optional)
*/ function createWorker(WorkerConstructor, workerPath, workerOptions) {
// Build the forwarded globals object
const forwardedGlobals = {};
for (const name of WORKER_FORWARDED_GLOBALS){
forwardedGlobals[name] = globalThis[name];
}
// Merge workerData with forwarded globals
const existingWorkerData = workerOptions?.workerData || {};
const options = {
...workerOptions,
workerData: {
...typeof existingWorkerData === 'object' ? existingWorkerData : {},
__turbopack_globals__: forwardedGlobals
}
};
return new WorkerConstructor(workerPath, options);
}
const regexJsUrl = /\.js(?:\?[^#]*)?(?:#.*)?$/;
/**
* Checks if a given path/URL ends with .js, optionally followed by ?query or #fragment.
*/ function isJs(chunkUrlOrPath) {
return regexJsUrl.test(chunkUrlOrPath);
}
/* eslint-disable @typescript-eslint/no-unused-vars */ /// <reference path="./runtime-base.ts" />
/**
* Production Node.js runtime.
* Uses ModuleWithDirection and simple module instantiation without HMR support.
*/ // moduleCache and moduleFactories are declared in runtime-base.ts
// this is read in runtime-utils.ts so it creates a module with direction for hmr
createModuleWithDirectionFlag = true;
const nodeContextPrototype = Context.prototype;
nodeContextPrototype.q = exportUrl;
nodeContextPrototype.M = moduleFactories;
// Cast moduleCache to ModuleWithDirection for production mode
nodeContextPrototype.c = moduleCache;
nodeContextPrototype.R = resolvePathFromModule;
nodeContextPrototype.b = createWorker;
nodeContextPrototype.C = clearChunkCache;
function instantiateModule(id, sourceType, sourceData) {
const moduleFactory = moduleFactories.get(id);
if (typeof moduleFactory !== 'function') {
// This can happen if modules incorrectly handle HMR disposes/updates,
// e.g. when they keep a `setTimeout` around which still executes old code
// and contains e.g. a `require("something")` call.
throw new Error(factoryNotAvailableMessage(id, sourceType, sourceData));
}
const module1 = createModuleWithDirection(id);
const exports = module1.exports;
moduleCache[id] = module1;
const context = new Context(module1, exports);
// NOTE(alexkirsz) This can fail when the module encounters a runtime error.
try {
moduleFactory(context, module1, exports);
} catch (error) {
module1.error = error;
throw error;
}
;
module1.loaded = true;
if (module1.namespaceObject && module1.exports !== module1.namespaceObject) {
// in case of a circular dependency: cjs1 -> esm2 -> cjs1
interopEsm(module1.exports, module1.namespaceObject);
}
return module1;
}
/**
* Retrieves a module from the cache, or instantiate it if it is not cached.
*/ // @ts-ignore
function getOrInstantiateModuleFromParent(id, sourceModule) {
const module1 = moduleCache[id];
if (module1) {
if (module1.error) {
throw module1.error;
}
return module1;
}
return instantiateModule(id, SourceType.Parent, sourceModule.id);
}
/**
* Instantiates a runtime module.
*/ function instantiateRuntimeModule(chunkPath, moduleId) {
return instantiateModule(moduleId, SourceType.Runtime, chunkPath);
}
/**
* Retrieves a module from the cache, or instantiate it as a runtime module if it is not cached.
*/ // @ts-ignore TypeScript doesn't separate this module space from the browser runtime
function getOrInstantiateRuntimeModule(chunkPath, moduleId) {
const module1 = moduleCache[moduleId];
if (module1) {
if (module1.error) {
throw module1.error;
}
return module1;
}
return instantiateRuntimeModule(chunkPath, moduleId);
}
module.exports = (sourcePath)=>({
m: (id)=>getOrInstantiateRuntimeModule(sourcePath, id),
c: (chunkData)=>loadRuntimeChunk(sourcePath, chunkData)
});
//# sourceMappingURL=%5Bturbopack%5D_runtime.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
{"type": "commonjs"}
+1
View File
@@ -0,0 +1 @@
{"previewModeId":"27f0f448c7612d99367a5f2ad3ef640d","previewModeSigningKey":"469588a4123d872c601d6b7e46a81a0293be778414e874ade1dd894e5043ed18","previewModeEncryptionKey":"4a32c4a98be7f6aa59c45d2df6499282db46fc75be9b9c20202a11465a1c588e","expireAt":1782368592282}
+1
View File
@@ -0,0 +1 @@
{"encryption.key":"rwAwLx2fk2wbc+k6wADc7BSosNYJAwa6zblnOMU+nFc=","encryption.expire_at":1782368591986}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,6 @@
{
"buildStage": "static-generation",
"buildOptions": {
"useBuildWorker": "true"
}
}
@@ -0,0 +1 @@
{"name":"Next.js","version":"16.2.8"}
@@ -0,0 +1,282 @@
[
{
"route": "/dashboard/site-config",
"firstLoadUncompressedJsBytes": 582588,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/0uk61hc83wuns.js",
".next/static/chunks/0r14kfqe43tub.js",
".next/static/chunks/2whz8frja7po-.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/dashboard/companies/[id]",
"firstLoadUncompressedJsBytes": 572521,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/0uk61hc83wuns.js",
".next/static/chunks/0ftm9qkpl7qx7.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/dashboard/pricing",
"firstLoadUncompressedJsBytes": 568782,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/0uk61hc83wuns.js",
".next/static/chunks/28c_rrttruhlp.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/dashboard/billing",
"firstLoadUncompressedJsBytes": 566874,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/0uk61hc83wuns.js",
".next/static/chunks/27az1pyngxlsz.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/dashboard/menu-management",
"firstLoadUncompressedJsBytes": 555732,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/0uk61hc83wuns.js",
".next/static/chunks/2ugxxdv2czoee.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/dashboard/containers",
"firstLoadUncompressedJsBytes": 550410,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/0uk61hc83wuns.js",
".next/static/chunks/2_lq6leer_gua.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/dashboard/admin-users",
"firstLoadUncompressedJsBytes": 546840,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/0uk61hc83wuns.js",
".next/static/chunks/32xus5prj3hqj.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/dashboard/notifications",
"firstLoadUncompressedJsBytes": 544442,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/0uk61hc83wuns.js",
".next/static/chunks/3v_-a-9hx_lw5.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/dashboard/companies",
"firstLoadUncompressedJsBytes": 544223,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/0uk61hc83wuns.js",
".next/static/chunks/0xq7_2ktak4rb.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/dashboard/renters",
"firstLoadUncompressedJsBytes": 543111,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/0uk61hc83wuns.js",
".next/static/chunks/0wwp54sprh-2v.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/dashboard",
"firstLoadUncompressedJsBytes": 541745,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/0uk61hc83wuns.js",
".next/static/chunks/0tgw0ys6ar29k.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/dashboard/audit-logs",
"firstLoadUncompressedJsBytes": 541648,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/0uk61hc83wuns.js",
".next/static/chunks/1upk0tvhu5p1u.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/reset-password",
"firstLoadUncompressedJsBytes": 540430,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/0rygltw2dxjw9.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/forgot-password",
"firstLoadUncompressedJsBytes": 538901,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/3t7upkfpy4qk3.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/auth-redirect",
"firstLoadUncompressedJsBytes": 523947,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/2r7tgel-fszrc.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/",
"firstLoadUncompressedJsBytes": 523181,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/_not-found",
"firstLoadUncompressedJsBytes": 523181,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
},
{
"route": "/login",
"firstLoadUncompressedJsBytes": 523181,
"firstLoadChunkPaths": [
".next/static/chunks/05-c3ty_6dwfk.js",
".next/static/chunks/18sotvvmcs59d.js",
".next/static/chunks/10txdscg_s8qk.js",
".next/static/chunks/3fi7ta8l6_q46.js",
".next/static/chunks/2de_cmw_l_puw.js",
".next/static/chunks/3svce10uq2e6q.js",
".next/static/chunks/40z7xw1jd_fv0.js",
".next/static/chunks/turbopack-1kvzti-0-yxfi.js"
]
}
]
+6
View File
@@ -0,0 +1,6 @@
{
"version": 1,
"hasExportPathMap": false,
"exportTrailingSlash": false,
"isNextImageImported": false
}
@@ -0,0 +1,13 @@
{
"pages": {
"/_app": []
},
"devFiles": [],
"polyfillFiles": [],
"lowPriorityFiles": [
"static/jRlQg50qYlv2hlr5AFzlp/_buildManifest.js",
"static/jRlQg50qYlv2hlr5AFzlp/_ssgManifest.js",
"static/jRlQg50qYlv2hlr5AFzlp/_clientMiddlewareManifest.js"
],
"rootMainFiles": []
}
+80
View File
@@ -0,0 +1,80 @@
{
"version": 1,
"images": {
"deviceSizes": [
640,
750,
828,
1080,
1200,
1920,
2048,
3840
],
"imageSizes": [
32,
48,
64,
96,
128,
256,
384
],
"path": "/admin/_next/image",
"loader": "default",
"loaderFile": "",
"domains": [],
"disableStaticImages": false,
"minimumCacheTTL": 14400,
"formats": [
"image/webp"
],
"maximumRedirects": 3,
"maximumResponseBody": 50000000,
"dangerouslyAllowLocalIP": false,
"dangerouslyAllowSVG": false,
"contentSecurityPolicy": "script-src 'none'; frame-src 'none'; sandbox;",
"contentDispositionType": "attachment",
"localPatterns": [
{
"pathname": "^(?:(?!(?:^|\\/)\\.{1,2}(?:\\/|$))(?:(?:(?!(?:^|\\/)\\.{1,2}(?:\\/|$)).)*?)\\/?)$",
"search": ""
}
],
"remotePatterns": [
{
"protocol": "https",
"hostname": "^(?:^(?:res\\.cloudinary\\.com)$)$",
"pathname": "^(?:(?!(?:^|\\/)\\.{1,2}(?:\\/|$))(?:(?:(?!(?:^|\\/)\\.{1,2}(?:\\/|$)).)*?)\\/?)$"
},
{
"protocol": "http",
"hostname": "^(?:^(?:localhost)$)$",
"port": "4000",
"pathname": "^(?:\\/storage(?:\\/(?!\\.{1,2}(?:\\/|$))(?:(?:(?!(?:^|\\/)\\.{1,2}(?:\\/|$)).)*?)|$))$"
}
],
"qualities": [
75
],
"unoptimized": false,
"customCacheHandler": false,
"sizes": [
640,
750,
828,
1080,
1200,
1920,
2048,
3840,
32,
48,
64,
96,
128,
256,
384
]
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
{"type": "commonjs"}
+450
View File
@@ -0,0 +1,450 @@
{
"version": 4,
"routes": {
"/": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/",
"dataRoute": "/index.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/_global-error": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/_global-error",
"dataRoute": "/_global-error.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/_not-found": {
"initialStatus": 404,
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/_not-found",
"dataRoute": "/_not-found.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/auth-redirect": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/auth-redirect",
"dataRoute": "/auth-redirect.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/dashboard": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/dashboard",
"dataRoute": "/dashboard.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/dashboard/admin-users": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/dashboard/admin-users",
"dataRoute": "/dashboard/admin-users.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/dashboard/audit-logs": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/dashboard/audit-logs",
"dataRoute": "/dashboard/audit-logs.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/dashboard/billing": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/dashboard/billing",
"dataRoute": "/dashboard/billing.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/dashboard/companies": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/dashboard/companies",
"dataRoute": "/dashboard/companies.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/dashboard/containers": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/dashboard/containers",
"dataRoute": "/dashboard/containers.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/dashboard/menu-management": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/dashboard/menu-management",
"dataRoute": "/dashboard/menu-management.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/dashboard/notifications": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/dashboard/notifications",
"dataRoute": "/dashboard/notifications.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/dashboard/pricing": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/dashboard/pricing",
"dataRoute": "/dashboard/pricing.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/dashboard/renters": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/dashboard/renters",
"dataRoute": "/dashboard/renters.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/dashboard/site-config": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/dashboard/site-config",
"dataRoute": "/dashboard/site-config.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/forgot-password": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/forgot-password",
"dataRoute": "/forgot-password.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/icon": {
"initialHeaders": {
"cache-control": "public, max-age=0, must-revalidate",
"content-type": "image/png",
"x-next-cache-tags": "_N_T_/layout,_N_T_/icon/layout,_N_T_/icon/route,_N_T_/icon"
},
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/icon",
"dataRoute": null,
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
},
"/reset-password": {
"experimentalBypassFor": [
{
"type": "header",
"key": "next-action"
},
{
"type": "header",
"key": "content-type",
"value": "multipart/form-data;.*"
}
],
"initialRevalidateSeconds": false,
"srcRoute": "/reset-password",
"dataRoute": "/reset-password.rsc",
"allowHeader": [
"host",
"x-matched-path",
"x-prerender-revalidate",
"x-prerender-revalidate-if-generated",
"x-next-revalidated-tags",
"x-next-revalidate-tag-token"
]
}
},
"dynamicRoutes": {},
"notFoundRoutes": [],
"preview": {
"previewModeId": "27f0f448c7612d99367a5f2ad3ef640d",
"previewModeSigningKey": "469588a4123d872c601d6b7e46a81a0293be778414e874ade1dd894e5043ed18",
"previewModeEncryptionKey": "4a32c4a98be7f6aa59c45d2df6499282db46fc75be9b9c20202a11465a1c588e"
}
}
+357
View File
@@ -0,0 +1,357 @@
self.__SERVER_FILES_MANIFEST={
"version": 1,
"config": {
"env": {},
"webpack": null,
"typescript": {
"ignoreBuildErrors": false
},
"typedRoutes": false,
"distDir": ".next",
"cleanDistDir": true,
"assetPrefix": "/admin",
"cacheMaxMemorySize": 52428800,
"configOrigin": "next.config.js",
"useFileSystemPublicRoutes": true,
"generateEtags": true,
"pageExtensions": [
"tsx",
"ts",
"jsx",
"js"
],
"poweredByHeader": true,
"compress": true,
"images": {
"deviceSizes": [
640,
750,
828,
1080,
1200,
1920,
2048,
3840
],
"imageSizes": [
32,
48,
64,
96,
128,
256,
384
],
"path": "/admin/_next/image",
"loader": "default",
"loaderFile": "",
"domains": [],
"disableStaticImages": false,
"minimumCacheTTL": 14400,
"formats": [
"image/webp"
],
"maximumRedirects": 3,
"maximumResponseBody": 50000000,
"dangerouslyAllowLocalIP": false,
"dangerouslyAllowSVG": false,
"contentSecurityPolicy": "script-src 'none'; frame-src 'none'; sandbox;",
"contentDispositionType": "attachment",
"localPatterns": [
{
"pathname": "**",
"search": ""
}
],
"remotePatterns": [
{
"protocol": "https",
"hostname": "res.cloudinary.com"
},
{
"protocol": "http",
"hostname": "localhost",
"port": "4000",
"pathname": "/storage/**"
}
],
"qualities": [
75
],
"unoptimized": false,
"customCacheHandler": false
},
"devIndicators": {
"position": "bottom-left"
},
"onDemandEntries": {
"maxInactiveAge": 60000,
"pagesBufferLength": 5
},
"basePath": "/admin",
"sassOptions": {},
"trailingSlash": false,
"i18n": null,
"productionBrowserSourceMaps": false,
"excludeDefaultMomentLocales": true,
"reactProductionProfiling": false,
"reactStrictMode": null,
"reactMaxHeadersLength": 6000,
"httpAgentOptions": {
"keepAlive": true
},
"logging": {
"serverFunctions": true,
"browserToTerminal": "warn"
},
"compiler": {},
"expireTime": 31536000,
"staticPageGenerationTimeout": 60,
"modularizeImports": {
"@mui/icons-material": {
"transform": "@mui/icons-material/{{member}}"
},
"lodash": {
"transform": "lodash/{{member}}"
}
},
"outputFileTracingRoot": "/Volumes/ExternalApps/Documents/alrahma_sunday_school_api",
"cacheComponents": false,
"cacheLife": {
"default": {
"stale": 300,
"revalidate": 900,
"expire": 4294967294
},
"seconds": {
"stale": 30,
"revalidate": 1,
"expire": 60
},
"minutes": {
"stale": 300,
"revalidate": 60,
"expire": 3600
},
"hours": {
"stale": 300,
"revalidate": 3600,
"expire": 86400
},
"days": {
"stale": 300,
"revalidate": 86400,
"expire": 604800
},
"weeks": {
"stale": 300,
"revalidate": 604800,
"expire": 2592000
},
"max": {
"stale": 300,
"revalidate": 2592000,
"expire": 31536000
}
},
"cacheHandlers": {},
"experimental": {
"appNewScrollHandler": false,
"useSkewCookie": false,
"cssChunking": true,
"multiZoneDraftMode": false,
"appNavFailHandling": false,
"prerenderEarlyExit": true,
"serverMinification": true,
"linkNoTouchStart": false,
"caseSensitiveRoutes": false,
"cachedNavigations": false,
"partialFallbacks": false,
"dynamicOnHover": false,
"varyParams": false,
"prefetchInlining": false,
"preloadEntriesOnStart": true,
"clientRouterFilter": true,
"clientRouterFilterRedirects": false,
"fetchCacheKeyPrefix": "",
"proxyPrefetch": "flexible",
"optimisticClientCache": true,
"manualClientBasePath": false,
"cpus": 9,
"memoryBasedWorkersCount": false,
"imgOptConcurrency": null,
"imgOptTimeoutInSeconds": 7,
"imgOptMaxInputPixels": 268402689,
"imgOptSequentialRead": null,
"imgOptSkipMetadata": null,
"isrFlushToDisk": true,
"workerThreads": false,
"optimizeCss": false,
"nextScriptWorkers": false,
"scrollRestoration": false,
"externalDir": false,
"disableOptimizedLoading": false,
"gzipSize": true,
"craCompat": false,
"esmExternals": true,
"fullySpecified": false,
"swcTraceProfiling": false,
"forceSwcTransforms": false,
"largePageDataBytes": 128000,
"typedEnv": false,
"parallelServerCompiles": false,
"parallelServerBuildTraces": false,
"ppr": false,
"authInterrupts": false,
"webpackMemoryOptimizations": false,
"optimizeServerReact": true,
"strictRouteTypes": false,
"viewTransition": false,
"removeUncaughtErrorAndRejectionListeners": false,
"validateRSCRequestHeaders": false,
"staleTimes": {
"dynamic": 0,
"static": 300
},
"reactDebugChannel": true,
"serverComponentsHmrCache": true,
"staticGenerationMaxConcurrency": 8,
"staticGenerationMinPagesPerWorker": 25,
"transitionIndicator": false,
"gestureTransition": false,
"inlineCss": false,
"useCache": false,
"globalNotFound": false,
"browserDebugInfoInTerminal": "warn",
"lockDistDir": true,
"proxyClientMaxBodySize": 10485760,
"hideLogsAfterAbort": false,
"mcpServer": true,
"turbopackFileSystemCacheForDev": true,
"turbopackFileSystemCacheForBuild": false,
"turbopackInferModuleSideEffects": true,
"turbopackPluginRuntimeStrategy": "childProcesses",
"optimizePackageImports": [
"lucide-react",
"date-fns",
"lodash-es",
"ramda",
"antd",
"react-bootstrap",
"ahooks",
"@ant-design/icons",
"@headlessui/react",
"@headlessui-float/react",
"@heroicons/react/20/solid",
"@heroicons/react/24/solid",
"@heroicons/react/24/outline",
"@visx/visx",
"@tremor/react",
"rxjs",
"@mui/material",
"@mui/icons-material",
"recharts",
"react-use",
"effect",
"@effect/schema",
"@effect/platform",
"@effect/platform-node",
"@effect/platform-browser",
"@effect/platform-bun",
"@effect/sql",
"@effect/sql-mssql",
"@effect/sql-mysql2",
"@effect/sql-pg",
"@effect/sql-sqlite-node",
"@effect/sql-sqlite-bun",
"@effect/sql-sqlite-wasm",
"@effect/sql-sqlite-react-native",
"@effect/rpc",
"@effect/rpc-http",
"@effect/typeclass",
"@effect/experimental",
"@effect/opentelemetry",
"@material-ui/core",
"@material-ui/icons",
"@tabler/icons-react",
"mui-core",
"react-icons/ai",
"react-icons/bi",
"react-icons/bs",
"react-icons/cg",
"react-icons/ci",
"react-icons/di",
"react-icons/fa",
"react-icons/fa6",
"react-icons/fc",
"react-icons/fi",
"react-icons/gi",
"react-icons/go",
"react-icons/gr",
"react-icons/hi",
"react-icons/hi2",
"react-icons/im",
"react-icons/io",
"react-icons/io5",
"react-icons/lia",
"react-icons/lib",
"react-icons/lu",
"react-icons/md",
"react-icons/pi",
"react-icons/ri",
"react-icons/rx",
"react-icons/si",
"react-icons/sl",
"react-icons/tb",
"react-icons/tfi",
"react-icons/ti",
"react-icons/vsc",
"react-icons/wi"
],
"trustHostHeader": false,
"isExperimentalCompile": false
},
"htmlLimitedBots": "[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight",
"bundlePagesRouterDependencies": false,
"configFileName": "next.config.js",
"transpilePackages": [
"@rentaldrivego/types"
],
"turbopack": {
"root": "/Volumes/ExternalApps/Documents/alrahma_sunday_school_api"
},
"distDirRoot": ".next",
"_originalRewrites": {
"beforeFiles": [],
"afterFiles": [
{
"source": "/api/:path*",
"destination": "http://localhost:4000/api/:path*"
}
],
"fallback": []
}
},
"appDir": "/Volumes/ExternalApps/Documents/alrahma_sunday_school_api/apps/admin",
"relativeAppDir": "apps/admin",
"files": [
".next/package.json",
".next/routes-manifest.json",
".next/server/pages-manifest.json",
".next/build-manifest.json",
".next/prerender-manifest.json",
".next/server/functions-config-manifest.json",
".next/server/middleware-manifest.json",
".next/server/middleware-build-manifest.js",
".next/server/app-paths-manifest.json",
".next/app-path-routes-manifest.json",
".next/server/server-reference-manifest.js",
".next/server/server-reference-manifest.json",
".next/server/prefetch-hints.json",
".next/BUILD_ID",
".next/server/next-font-manifest.js",
".next/server/next-font-manifest.json",
".next/required-server-files.json"
],
"ignore": []
}
+357
View File
@@ -0,0 +1,357 @@
{
"version": 1,
"config": {
"env": {},
"webpack": null,
"typescript": {
"ignoreBuildErrors": false
},
"typedRoutes": false,
"distDir": ".next",
"cleanDistDir": true,
"assetPrefix": "/admin",
"cacheMaxMemorySize": 52428800,
"configOrigin": "next.config.js",
"useFileSystemPublicRoutes": true,
"generateEtags": true,
"pageExtensions": [
"tsx",
"ts",
"jsx",
"js"
],
"poweredByHeader": true,
"compress": true,
"images": {
"deviceSizes": [
640,
750,
828,
1080,
1200,
1920,
2048,
3840
],
"imageSizes": [
32,
48,
64,
96,
128,
256,
384
],
"path": "/admin/_next/image",
"loader": "default",
"loaderFile": "",
"domains": [],
"disableStaticImages": false,
"minimumCacheTTL": 14400,
"formats": [
"image/webp"
],
"maximumRedirects": 3,
"maximumResponseBody": 50000000,
"dangerouslyAllowLocalIP": false,
"dangerouslyAllowSVG": false,
"contentSecurityPolicy": "script-src 'none'; frame-src 'none'; sandbox;",
"contentDispositionType": "attachment",
"localPatterns": [
{
"pathname": "**",
"search": ""
}
],
"remotePatterns": [
{
"protocol": "https",
"hostname": "res.cloudinary.com"
},
{
"protocol": "http",
"hostname": "localhost",
"port": "4000",
"pathname": "/storage/**"
}
],
"qualities": [
75
],
"unoptimized": false,
"customCacheHandler": false
},
"devIndicators": {
"position": "bottom-left"
},
"onDemandEntries": {
"maxInactiveAge": 60000,
"pagesBufferLength": 5
},
"basePath": "/admin",
"sassOptions": {},
"trailingSlash": false,
"i18n": null,
"productionBrowserSourceMaps": false,
"excludeDefaultMomentLocales": true,
"reactProductionProfiling": false,
"reactStrictMode": null,
"reactMaxHeadersLength": 6000,
"httpAgentOptions": {
"keepAlive": true
},
"logging": {
"serverFunctions": true,
"browserToTerminal": "warn"
},
"compiler": {},
"expireTime": 31536000,
"staticPageGenerationTimeout": 60,
"modularizeImports": {
"@mui/icons-material": {
"transform": "@mui/icons-material/{{member}}"
},
"lodash": {
"transform": "lodash/{{member}}"
}
},
"outputFileTracingRoot": "/Volumes/ExternalApps/Documents/alrahma_sunday_school_api",
"cacheComponents": false,
"cacheLife": {
"default": {
"stale": 300,
"revalidate": 900,
"expire": 4294967294
},
"seconds": {
"stale": 30,
"revalidate": 1,
"expire": 60
},
"minutes": {
"stale": 300,
"revalidate": 60,
"expire": 3600
},
"hours": {
"stale": 300,
"revalidate": 3600,
"expire": 86400
},
"days": {
"stale": 300,
"revalidate": 86400,
"expire": 604800
},
"weeks": {
"stale": 300,
"revalidate": 604800,
"expire": 2592000
},
"max": {
"stale": 300,
"revalidate": 2592000,
"expire": 31536000
}
},
"cacheHandlers": {},
"experimental": {
"appNewScrollHandler": false,
"useSkewCookie": false,
"cssChunking": true,
"multiZoneDraftMode": false,
"appNavFailHandling": false,
"prerenderEarlyExit": true,
"serverMinification": true,
"linkNoTouchStart": false,
"caseSensitiveRoutes": false,
"cachedNavigations": false,
"partialFallbacks": false,
"dynamicOnHover": false,
"varyParams": false,
"prefetchInlining": false,
"preloadEntriesOnStart": true,
"clientRouterFilter": true,
"clientRouterFilterRedirects": false,
"fetchCacheKeyPrefix": "",
"proxyPrefetch": "flexible",
"optimisticClientCache": true,
"manualClientBasePath": false,
"cpus": 9,
"memoryBasedWorkersCount": false,
"imgOptConcurrency": null,
"imgOptTimeoutInSeconds": 7,
"imgOptMaxInputPixels": 268402689,
"imgOptSequentialRead": null,
"imgOptSkipMetadata": null,
"isrFlushToDisk": true,
"workerThreads": false,
"optimizeCss": false,
"nextScriptWorkers": false,
"scrollRestoration": false,
"externalDir": false,
"disableOptimizedLoading": false,
"gzipSize": true,
"craCompat": false,
"esmExternals": true,
"fullySpecified": false,
"swcTraceProfiling": false,
"forceSwcTransforms": false,
"largePageDataBytes": 128000,
"typedEnv": false,
"parallelServerCompiles": false,
"parallelServerBuildTraces": false,
"ppr": false,
"authInterrupts": false,
"webpackMemoryOptimizations": false,
"optimizeServerReact": true,
"strictRouteTypes": false,
"viewTransition": false,
"removeUncaughtErrorAndRejectionListeners": false,
"validateRSCRequestHeaders": false,
"staleTimes": {
"dynamic": 0,
"static": 300
},
"reactDebugChannel": true,
"serverComponentsHmrCache": true,
"staticGenerationMaxConcurrency": 8,
"staticGenerationMinPagesPerWorker": 25,
"transitionIndicator": false,
"gestureTransition": false,
"inlineCss": false,
"useCache": false,
"globalNotFound": false,
"browserDebugInfoInTerminal": "warn",
"lockDistDir": true,
"proxyClientMaxBodySize": 10485760,
"hideLogsAfterAbort": false,
"mcpServer": true,
"turbopackFileSystemCacheForDev": true,
"turbopackFileSystemCacheForBuild": false,
"turbopackInferModuleSideEffects": true,
"turbopackPluginRuntimeStrategy": "childProcesses",
"optimizePackageImports": [
"lucide-react",
"date-fns",
"lodash-es",
"ramda",
"antd",
"react-bootstrap",
"ahooks",
"@ant-design/icons",
"@headlessui/react",
"@headlessui-float/react",
"@heroicons/react/20/solid",
"@heroicons/react/24/solid",
"@heroicons/react/24/outline",
"@visx/visx",
"@tremor/react",
"rxjs",
"@mui/material",
"@mui/icons-material",
"recharts",
"react-use",
"effect",
"@effect/schema",
"@effect/platform",
"@effect/platform-node",
"@effect/platform-browser",
"@effect/platform-bun",
"@effect/sql",
"@effect/sql-mssql",
"@effect/sql-mysql2",
"@effect/sql-pg",
"@effect/sql-sqlite-node",
"@effect/sql-sqlite-bun",
"@effect/sql-sqlite-wasm",
"@effect/sql-sqlite-react-native",
"@effect/rpc",
"@effect/rpc-http",
"@effect/typeclass",
"@effect/experimental",
"@effect/opentelemetry",
"@material-ui/core",
"@material-ui/icons",
"@tabler/icons-react",
"mui-core",
"react-icons/ai",
"react-icons/bi",
"react-icons/bs",
"react-icons/cg",
"react-icons/ci",
"react-icons/di",
"react-icons/fa",
"react-icons/fa6",
"react-icons/fc",
"react-icons/fi",
"react-icons/gi",
"react-icons/go",
"react-icons/gr",
"react-icons/hi",
"react-icons/hi2",
"react-icons/im",
"react-icons/io",
"react-icons/io5",
"react-icons/lia",
"react-icons/lib",
"react-icons/lu",
"react-icons/md",
"react-icons/pi",
"react-icons/ri",
"react-icons/rx",
"react-icons/si",
"react-icons/sl",
"react-icons/tb",
"react-icons/tfi",
"react-icons/ti",
"react-icons/vsc",
"react-icons/wi"
],
"trustHostHeader": false,
"isExperimentalCompile": false
},
"htmlLimitedBots": "[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight",
"bundlePagesRouterDependencies": false,
"configFileName": "next.config.js",
"transpilePackages": [
"@rentaldrivego/types"
],
"turbopack": {
"root": "/Volumes/ExternalApps/Documents/alrahma_sunday_school_api"
},
"distDirRoot": ".next",
"_originalRewrites": {
"beforeFiles": [],
"afterFiles": [
{
"source": "/api/:path*",
"destination": "http://localhost:4000/api/:path*"
}
],
"fallback": []
}
},
"appDir": "/Volumes/ExternalApps/Documents/alrahma_sunday_school_api/apps/admin",
"relativeAppDir": "apps/admin",
"files": [
".next/package.json",
".next/routes-manifest.json",
".next/server/pages-manifest.json",
".next/build-manifest.json",
".next/prerender-manifest.json",
".next/server/functions-config-manifest.json",
".next/server/middleware-manifest.json",
".next/server/middleware-build-manifest.js",
".next/server/app-paths-manifest.json",
".next/app-path-routes-manifest.json",
".next/server/server-reference-manifest.js",
".next/server/server-reference-manifest.json",
".next/server/prefetch-hints.json",
".next/BUILD_ID",
".next/server/next-font-manifest.js",
".next/server/next-font-manifest.json",
".next/required-server-files.json"
],
"ignore": []
}
+220
View File
@@ -0,0 +1,220 @@
{
"version": 3,
"pages404": true,
"appType": "app",
"caseSensitive": false,
"basePath": "/admin",
"redirects": [
{
"source": "/admin/",
"destination": "/admin",
"basePath": false,
"internal": true,
"priority": true,
"statusCode": 308,
"regex": "^/admin/$"
},
{
"source": "/:path+/",
"destination": "/:path+",
"internal": true,
"priority": true,
"statusCode": 308,
"regex": "^(?:/((?:[^/]+?)(?:/(?:[^/]+?))*))/$"
}
],
"headers": [
{
"source": "/admin/:path*",
"headers": [
{
"key": "Strict-Transport-Security",
"value": "max-age=31536000; includeSubDomains"
},
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-Frame-Options",
"value": "DENY"
},
{
"key": "Referrer-Policy",
"value": "strict-origin-when-cross-origin"
},
{
"key": "Permissions-Policy",
"value": "camera=(), microphone=(), geolocation=()"
},
{
"key": "Content-Security-Policy",
"value": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; font-src 'self' data:; connect-src 'self' https: wss:; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; object-src 'none'"
}
],
"regex": "^/admin(?:/((?:[^/]+?)(?:/(?:[^/]+?))*))?(?:/)?$"
}
],
"onMatchHeaders": [],
"rewrites": {
"beforeFiles": [],
"afterFiles": [
{
"source": "/admin/api/:path*",
"destination": "http://localhost:4000/api/:path*",
"regex": "^/admin/api(?:/((?:[^/]+?)(?:/(?:[^/]+?))*))?(?:/)?$"
}
],
"fallback": []
},
"dynamicRoutes": [
{
"page": "/dashboard/companies/[id]",
"regex": "^/dashboard/companies/([^/]+?)(?:/)?$",
"routeKeys": {
"nxtPid": "nxtPid"
},
"namedRegex": "^/dashboard/companies/(?<nxtPid>[^/]+?)(?:/)?$"
}
],
"staticRoutes": [
{
"page": "/",
"regex": "^/(?:/)?$",
"routeKeys": {},
"namedRegex": "^/(?:/)?$"
},
{
"page": "/_global-error",
"regex": "^/_global\\-error(?:/)?$",
"routeKeys": {},
"namedRegex": "^/_global\\-error(?:/)?$"
},
{
"page": "/_not-found",
"regex": "^/_not\\-found(?:/)?$",
"routeKeys": {},
"namedRegex": "^/_not\\-found(?:/)?$"
},
{
"page": "/auth-redirect",
"regex": "^/auth\\-redirect(?:/)?$",
"routeKeys": {},
"namedRegex": "^/auth\\-redirect(?:/)?$"
},
{
"page": "/dashboard",
"regex": "^/dashboard(?:/)?$",
"routeKeys": {},
"namedRegex": "^/dashboard(?:/)?$"
},
{
"page": "/dashboard/admin-users",
"regex": "^/dashboard/admin\\-users(?:/)?$",
"routeKeys": {},
"namedRegex": "^/dashboard/admin\\-users(?:/)?$"
},
{
"page": "/dashboard/audit-logs",
"regex": "^/dashboard/audit\\-logs(?:/)?$",
"routeKeys": {},
"namedRegex": "^/dashboard/audit\\-logs(?:/)?$"
},
{
"page": "/dashboard/billing",
"regex": "^/dashboard/billing(?:/)?$",
"routeKeys": {},
"namedRegex": "^/dashboard/billing(?:/)?$"
},
{
"page": "/dashboard/companies",
"regex": "^/dashboard/companies(?:/)?$",
"routeKeys": {},
"namedRegex": "^/dashboard/companies(?:/)?$"
},
{
"page": "/dashboard/containers",
"regex": "^/dashboard/containers(?:/)?$",
"routeKeys": {},
"namedRegex": "^/dashboard/containers(?:/)?$"
},
{
"page": "/dashboard/menu-management",
"regex": "^/dashboard/menu\\-management(?:/)?$",
"routeKeys": {},
"namedRegex": "^/dashboard/menu\\-management(?:/)?$"
},
{
"page": "/dashboard/notifications",
"regex": "^/dashboard/notifications(?:/)?$",
"routeKeys": {},
"namedRegex": "^/dashboard/notifications(?:/)?$"
},
{
"page": "/dashboard/pricing",
"regex": "^/dashboard/pricing(?:/)?$",
"routeKeys": {},
"namedRegex": "^/dashboard/pricing(?:/)?$"
},
{
"page": "/dashboard/renters",
"regex": "^/dashboard/renters(?:/)?$",
"routeKeys": {},
"namedRegex": "^/dashboard/renters(?:/)?$"
},
{
"page": "/dashboard/site-config",
"regex": "^/dashboard/site\\-config(?:/)?$",
"routeKeys": {},
"namedRegex": "^/dashboard/site\\-config(?:/)?$"
},
{
"page": "/favicon.ico",
"regex": "^/favicon\\.ico(?:/)?$",
"routeKeys": {},
"namedRegex": "^/favicon\\.ico(?:/)?$"
},
{
"page": "/forgot-password",
"regex": "^/forgot\\-password(?:/)?$",
"routeKeys": {},
"namedRegex": "^/forgot\\-password(?:/)?$"
},
{
"page": "/icon",
"regex": "^/icon(?:/)?$",
"routeKeys": {},
"namedRegex": "^/icon(?:/)?$"
},
{
"page": "/login",
"regex": "^/login(?:/)?$",
"routeKeys": {},
"namedRegex": "^/login(?:/)?$"
},
{
"page": "/reset-password",
"regex": "^/reset\\-password(?:/)?$",
"routeKeys": {},
"namedRegex": "^/reset\\-password(?:/)?$"
}
],
"dataRoutes": [],
"rsc": {
"header": "rsc",
"varyHeader": "rsc, next-router-state-tree, next-router-prefetch, next-router-segment-prefetch",
"prefetchHeader": "next-router-prefetch",
"didPostponeHeader": "x-nextjs-postponed",
"contentTypeHeader": "text/x-component",
"suffix": ".rsc",
"prefetchSegmentHeader": "next-router-segment-prefetch",
"prefetchSegmentSuffix": ".segment.rsc",
"prefetchSegmentDirSuffix": ".segments",
"clientParamParsing": false,
"dynamicRSCPrerender": false
},
"rewriteHeaders": {
"pathHeader": "x-nextjs-rewritten-path",
"queryHeader": "x-nextjs-rewritten-query"
}
}
@@ -0,0 +1,23 @@
{
"/_global-error/page": "app/_global-error/page.js",
"/_not-found/page": "app/_not-found/page.js",
"/auth-redirect/page": "app/auth-redirect/page.js",
"/dashboard/admin-users/page": "app/dashboard/admin-users/page.js",
"/dashboard/audit-logs/page": "app/dashboard/audit-logs/page.js",
"/dashboard/billing/page": "app/dashboard/billing/page.js",
"/dashboard/companies/[id]/page": "app/dashboard/companies/[id]/page.js",
"/dashboard/companies/page": "app/dashboard/companies/page.js",
"/dashboard/containers/page": "app/dashboard/containers/page.js",
"/dashboard/menu-management/page": "app/dashboard/menu-management/page.js",
"/dashboard/notifications/page": "app/dashboard/notifications/page.js",
"/dashboard/page": "app/dashboard/page.js",
"/dashboard/pricing/page": "app/dashboard/pricing/page.js",
"/dashboard/renters/page": "app/dashboard/renters/page.js",
"/dashboard/site-config/page": "app/dashboard/site-config/page.js",
"/favicon.ico/route": "app/favicon.ico/route.js",
"/forgot-password/page": "app/forgot-password/page.js",
"/icon/route": "app/icon/route.js",
"/login/page": "app/login/page.js",
"/page": "app/page.js",
"/reset-password/page": "app/reset-password/page.js"
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
{
"status": 500,
"headers": {
"x-nextjs-stale-time": "300",
"x-nextjs-prerender": "1",
"x-next-cache-tags": "_N_T_/layout,_N_T_/_global-error/layout,_N_T_/_global-error/page,_N_T_/_global-error"
},
"segmentPaths": [
"/_tree",
"/_full",
"/__PAGE__",
"/_index",
"/_head"
]
}
@@ -0,0 +1,14 @@
1:"$Sreact.fragment"
2:I[39756,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default"]
3:I[37457,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default"]
4:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"OutletBoundary"]
5:"$Sreact.suspense"
8:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"ViewportBoundary"]
a:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"MetadataBoundary"]
c:I[68027,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default",1]
0:{"P":null,"c":["","_global-error"],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]}],[["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[["$","html",null,{"id":"__next_error__","children":[["$","head",null,{"children":[["$","title",null,{"children":"500: This page couldnt load"}],["$","style",null,{"dangerouslySetInnerHTML":{"__html":":root {--next-error-bg: #fff;--next-error-text: #171717;--next-error-title: #171717;--next-error-message: #171717;--next-error-digest: #666666;--next-error-btn-text: #fff;--next-error-btn-bg: #171717;--next-error-btn-border: none;--next-error-btn-secondary-text: #171717;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(0,0,0,0.08);}@media (prefers-color-scheme: dark) {:root {--next-error-bg: #0a0a0a;--next-error-text: #ededed;--next-error-title: #ededed;--next-error-message: #ededed;--next-error-digest: #a0a0a0;--next-error-btn-text: #0a0a0a;--next-error-btn-bg: #ededed;--next-error-btn-border: none;--next-error-btn-secondary-text: #ededed;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(255,255,255,0.14);}}body { margin: 0; color: var(--next-error-text); background: var(--next-error-bg); }"}}]]}],["$","body",null,{"children":["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","display":"flex","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"style":{"marginTop":"-32px","maxWidth":"325px","padding":"32px 28px","textAlign":"left"},"children":[["$","svg",null,{"width":"32","height":"32","viewBox":"-0.2 -1.5 32 32","fill":"none","style":{"marginBottom":"24px"},"children":["$","path",null,{"d":"M16.9328 0C18.0839 0.000116771 19.1334 0.658832 19.634 1.69531L31.4299 26.1309C32.0708 27.4588 31.1036 28.9999 29.6291 29H2.00215C0.527541 29 -0.439628 27.4588 0.201371 26.1309L11.9973 1.69531C12.4979 0.658823 13.5474 7.75066e-05 14.6984 0H16.9328ZM3.59493 26H28.0363L16.9328 3H14.6984L3.59493 26ZM15.8156 19C16.9202 19.0001 17.8156 19.8955 17.8156 21C17.8156 22.1045 16.9202 22.9999 15.8156 23C14.7111 23 13.8156 22.1046 13.8156 21C13.8156 19.8954 14.7111 19 15.8156 19ZM17.3156 16.5H14.3156V8.5H17.3156V16.5Z","fill":"var(--next-error-title)"}]}],["$","h1",null,{"style":{"fontSize":"24px","fontWeight":500,"letterSpacing":"-0.02em","lineHeight":"32px","margin":"0 0 12px 0","color":"var(--next-error-title)"},"children":"This page couldnt load"}],["$","p",null,{"style":{"fontSize":"14px","fontWeight":400,"lineHeight":"21px","margin":"0 0 20px 0","color":"var(--next-error-message)"},"children":"A server error occurred. Reload to try again."}],["$","form",null,{"style":{"margin":0},"children":["$","button",null,{"type":"submit","style":{"display":"inline-flex","alignItems":"center","justifyContent":"center","height":"32px","padding":"0 12px","fontSize":"14px","fontWeight":500,"lineHeight":"20px","borderRadius":"6px","cursor":"pointer","color":"var(--next-error-btn-text)","background":"var(--next-error-btn-bg)","border":"var(--next-error-btn-border)"},"children":"Reload"}]}]]}]}]}]]}],null,["$","$L4",null,{"children":["$","$5",null,{"name":"Next.MetadataOutlet","children":"$@6"}]}]]}],{},null,false,null]},null,false,"$@7"],["$","$1","h",{"children":[null,["$","$L8",null,{"children":"$L9"}],["$","div",null,{"hidden":true,"children":["$","$La",null,{"children":["$","$5",null,{"name":"Next.Metadata","children":"$Lb"}]}]}],null]}],false]],"m":"$undefined","G":["$c",[]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"jRlQg50qYlv2hlr5AFzlp"}
d:[]
7:"$Wd"
9:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
6:null
b:[]
@@ -0,0 +1,5 @@
1:"$Sreact.fragment"
2:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"OutletBoundary"]
3:"$Sreact.suspense"
0:{"rsc":["$","$1","c",{"children":[["$","html",null,{"id":"__next_error__","children":[["$","head",null,{"children":[["$","title",null,{"children":"500: This page couldnt load"}],["$","style",null,{"dangerouslySetInnerHTML":{"__html":":root {--next-error-bg: #fff;--next-error-text: #171717;--next-error-title: #171717;--next-error-message: #171717;--next-error-digest: #666666;--next-error-btn-text: #fff;--next-error-btn-bg: #171717;--next-error-btn-border: none;--next-error-btn-secondary-text: #171717;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(0,0,0,0.08);}@media (prefers-color-scheme: dark) {:root {--next-error-bg: #0a0a0a;--next-error-text: #ededed;--next-error-title: #ededed;--next-error-message: #ededed;--next-error-digest: #a0a0a0;--next-error-btn-text: #0a0a0a;--next-error-btn-bg: #ededed;--next-error-btn-border: none;--next-error-btn-secondary-text: #ededed;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(255,255,255,0.14);}}body { margin: 0; color: var(--next-error-text); background: var(--next-error-bg); }"}}]]}],["$","body",null,{"children":["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","display":"flex","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"style":{"marginTop":"-32px","maxWidth":"325px","padding":"32px 28px","textAlign":"left"},"children":[["$","svg",null,{"width":"32","height":"32","viewBox":"-0.2 -1.5 32 32","fill":"none","style":{"marginBottom":"24px"},"children":["$","path",null,{"d":"M16.9328 0C18.0839 0.000116771 19.1334 0.658832 19.634 1.69531L31.4299 26.1309C32.0708 27.4588 31.1036 28.9999 29.6291 29H2.00215C0.527541 29 -0.439628 27.4588 0.201371 26.1309L11.9973 1.69531C12.4979 0.658823 13.5474 7.75066e-05 14.6984 0H16.9328ZM3.59493 26H28.0363L16.9328 3H14.6984L3.59493 26ZM15.8156 19C16.9202 19.0001 17.8156 19.8955 17.8156 21C17.8156 22.1045 16.9202 22.9999 15.8156 23C14.7111 23 13.8156 22.1046 13.8156 21C13.8156 19.8954 14.7111 19 15.8156 19ZM17.3156 16.5H14.3156V8.5H17.3156V16.5Z","fill":"var(--next-error-title)"}]}],["$","h1",null,{"style":{"fontSize":"24px","fontWeight":500,"letterSpacing":"-0.02em","lineHeight":"32px","margin":"0 0 12px 0","color":"var(--next-error-title)"},"children":"This page couldnt load"}],["$","p",null,{"style":{"fontSize":"14px","fontWeight":400,"lineHeight":"21px","margin":"0 0 20px 0","color":"var(--next-error-message)"},"children":"A server error occurred. Reload to try again."}],["$","form",null,{"style":{"margin":0},"children":["$","button",null,{"type":"submit","style":{"display":"inline-flex","alignItems":"center","justifyContent":"center","height":"32px","padding":"0 12px","fontSize":"14px","fontWeight":500,"lineHeight":"20px","borderRadius":"6px","cursor":"pointer","color":"var(--next-error-btn-text)","background":"var(--next-error-btn-bg)","border":"var(--next-error-btn-border)"},"children":"Reload"}]}]]}]}]}]]}],null,["$","$L2",null,{"children":["$","$3",null,{"name":"Next.MetadataOutlet","children":"$@4"}]}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"jRlQg50qYlv2hlr5AFzlp"}
4:null
@@ -0,0 +1,14 @@
1:"$Sreact.fragment"
2:I[39756,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default"]
3:I[37457,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default"]
4:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"OutletBoundary"]
5:"$Sreact.suspense"
8:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"ViewportBoundary"]
a:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"MetadataBoundary"]
c:I[68027,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default",1]
0:{"P":null,"c":["","_global-error"],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]}],[["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[["$","html",null,{"id":"__next_error__","children":[["$","head",null,{"children":[["$","title",null,{"children":"500: This page couldnt load"}],["$","style",null,{"dangerouslySetInnerHTML":{"__html":":root {--next-error-bg: #fff;--next-error-text: #171717;--next-error-title: #171717;--next-error-message: #171717;--next-error-digest: #666666;--next-error-btn-text: #fff;--next-error-btn-bg: #171717;--next-error-btn-border: none;--next-error-btn-secondary-text: #171717;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(0,0,0,0.08);}@media (prefers-color-scheme: dark) {:root {--next-error-bg: #0a0a0a;--next-error-text: #ededed;--next-error-title: #ededed;--next-error-message: #ededed;--next-error-digest: #a0a0a0;--next-error-btn-text: #0a0a0a;--next-error-btn-bg: #ededed;--next-error-btn-border: none;--next-error-btn-secondary-text: #ededed;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(255,255,255,0.14);}}body { margin: 0; color: var(--next-error-text); background: var(--next-error-bg); }"}}]]}],["$","body",null,{"children":["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","display":"flex","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"style":{"marginTop":"-32px","maxWidth":"325px","padding":"32px 28px","textAlign":"left"},"children":[["$","svg",null,{"width":"32","height":"32","viewBox":"-0.2 -1.5 32 32","fill":"none","style":{"marginBottom":"24px"},"children":["$","path",null,{"d":"M16.9328 0C18.0839 0.000116771 19.1334 0.658832 19.634 1.69531L31.4299 26.1309C32.0708 27.4588 31.1036 28.9999 29.6291 29H2.00215C0.527541 29 -0.439628 27.4588 0.201371 26.1309L11.9973 1.69531C12.4979 0.658823 13.5474 7.75066e-05 14.6984 0H16.9328ZM3.59493 26H28.0363L16.9328 3H14.6984L3.59493 26ZM15.8156 19C16.9202 19.0001 17.8156 19.8955 17.8156 21C17.8156 22.1045 16.9202 22.9999 15.8156 23C14.7111 23 13.8156 22.1046 13.8156 21C13.8156 19.8954 14.7111 19 15.8156 19ZM17.3156 16.5H14.3156V8.5H17.3156V16.5Z","fill":"var(--next-error-title)"}]}],["$","h1",null,{"style":{"fontSize":"24px","fontWeight":500,"letterSpacing":"-0.02em","lineHeight":"32px","margin":"0 0 12px 0","color":"var(--next-error-title)"},"children":"This page couldnt load"}],["$","p",null,{"style":{"fontSize":"14px","fontWeight":400,"lineHeight":"21px","margin":"0 0 20px 0","color":"var(--next-error-message)"},"children":"A server error occurred. Reload to try again."}],["$","form",null,{"style":{"margin":0},"children":["$","button",null,{"type":"submit","style":{"display":"inline-flex","alignItems":"center","justifyContent":"center","height":"32px","padding":"0 12px","fontSize":"14px","fontWeight":500,"lineHeight":"20px","borderRadius":"6px","cursor":"pointer","color":"var(--next-error-btn-text)","background":"var(--next-error-btn-bg)","border":"var(--next-error-btn-border)"},"children":"Reload"}]}]]}]}]}]]}],null,["$","$L4",null,{"children":["$","$5",null,{"name":"Next.MetadataOutlet","children":"$@6"}]}]]}],{},null,false,null]},null,false,"$@7"],["$","$1","h",{"children":[null,["$","$L8",null,{"children":"$L9"}],["$","div",null,{"hidden":true,"children":["$","$La",null,{"children":["$","$5",null,{"name":"Next.Metadata","children":"$Lb"}]}]}],null]}],false]],"m":"$undefined","G":["$c",[]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"jRlQg50qYlv2hlr5AFzlp"}
d:[]
7:"$Wd"
9:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
6:null
b:[]
@@ -0,0 +1,5 @@
1:"$Sreact.fragment"
2:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"ViewportBoundary"]
3:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"MetadataBoundary"]
4:"$Sreact.suspense"
0:{"rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[]}]}]}],null]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"jRlQg50qYlv2hlr5AFzlp"}
@@ -0,0 +1,5 @@
1:"$Sreact.fragment"
2:I[39756,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default"]
3:I[37457,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default"]
4:[]
0:{"rsc":["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}]}]]}],"isPartial":false,"staleTime":300,"varyParams":"$W4","buildId":"jRlQg50qYlv2hlr5AFzlp"}
@@ -0,0 +1 @@
0:{"tree":{"name":"","param":null,"prefetchHints":0,"slots":{"children":{"name":"__PAGE__","param":null,"prefetchHints":0,"slots":null}}},"staleTime":300,"buildId":"jRlQg50qYlv2hlr5AFzlp"}
@@ -0,0 +1,9 @@
var R=require("../../chunks/ssr/[turbopack]_runtime.js")("server/app/_global-error/page.js")
R.c("server/chunks/ssr/[root-of-the-server]__06ss4iy._.js")
R.c("server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_19--w_z.js")
R.c("server/chunks/ssr/[root-of-the-server]__1k-d3jf._.js")
R.c("server/chunks/ssr/[root-of-the-server]__0nu24gp._.js")
R.c("server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0-o-goa.js")
R.c("server/chunks/ssr/apps_admin__next-internal_server_app__global-error_page_actions_1gzhnz9.js")
R.m(42378)
module.exports=R.m(42378).exports
@@ -0,0 +1,5 @@
{
"version": 3,
"sources": [],
"sections": []
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
{
"/_global-error/page": "app/_global-error/page.js"
}
@@ -0,0 +1,17 @@
{
"devFiles": [],
"ampDevFiles": [],
"polyfillFiles": [
"static/chunks/0cz1d0mv5g_q7.js"
],
"lowPriorityFiles": [],
"rootMainFiles": [
"static/chunks/3fi7ta8l6_q46.js",
"static/chunks/2de_cmw_l_puw.js",
"static/chunks/3svce10uq2e6q.js",
"static/chunks/40z7xw1jd_fv0.js",
"static/chunks/turbopack-1kvzti-0-yxfi.js"
],
"pages": {},
"ampFirstPages": []
}
@@ -0,0 +1,6 @@
{
"pages": {},
"app": {},
"appUsingSizeAdjust": false,
"pagesUsingSizeAdjust": false
}
@@ -0,0 +1,4 @@
{
"node": {},
"edge": {}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,16 @@
{
"status": 404,
"headers": {
"x-nextjs-stale-time": "300",
"x-nextjs-prerender": "1",
"x-next-cache-tags": "_N_T_/layout,_N_T_/_not-found/layout,_N_T_/_not-found/page,_N_T_/_not-found"
},
"segmentPaths": [
"/_tree",
"/_full",
"/_not-found/__PAGE__",
"/_not-found",
"/_index",
"/_head"
]
}
@@ -0,0 +1,17 @@
1:"$Sreact.fragment"
2:I[51224,["/admin/_next/static/chunks/10txdscg_s8qk.js"],"AdminI18nProvider"]
3:I[39756,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default"]
4:I[37457,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default"]
5:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"OutletBoundary"]
6:"$Sreact.suspense"
9:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"ViewportBoundary"]
b:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"MetadataBoundary"]
d:I[68027,["/admin/_next/static/chunks/10txdscg_s8qk.js"],"default",1]
:HL["/admin/_next/static/chunks/0_wwjs24psu3a.css","style"]
0:{"P":null,"c":["","_not-found"],"q":"","i":false,"f":[[["",{"children":["/_not-found",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/admin/_next/static/chunks/0_wwjs24psu3a.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/admin/_next/static/chunks/10txdscg_s8qk.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"light","suppressHydrationWarning":true,"children":[["$","head",null,{"children":["$","script",null,{"dangerouslySetInnerHTML":{"__html":"(function(){try{var m=document.cookie.match(/(?:^|; )rentaldrivego-theme=([^;]+)/);var theme=m?decodeURIComponent(m[1]):(localStorage.getItem('rentaldrivego-theme')||localStorage.getItem('admin-theme'));if(theme!=='light'&&theme!=='dark'){theme=window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'}document.documentElement.classList.remove('light','dark');document.documentElement.classList.add(theme);document.documentElement.style.colorScheme=theme;document.body&&document.body.setAttribute('data-theme',theme)}catch(e){}})();"}}]}],["$","body",null,{"suppressHydrationWarning":true,"children":["$","$L2",null,{"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],null,["$","$L5",null,{"children":["$","$6",null,{"name":"Next.MetadataOutlet","children":"$@7"}]}]]}],{},null,false,null]},null,false,"$@8"]},null,false,null],["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L9",null,{"children":"$La"}],["$","div",null,{"hidden":true,"children":["$","$Lb",null,{"children":["$","$6",null,{"name":"Next.Metadata","children":"$Lc"}]}]}],null]}],false]],"m":"$undefined","G":["$d",[["$","link","0",{"rel":"stylesheet","href":"/admin/_next/static/chunks/0_wwjs24psu3a.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"jRlQg50qYlv2hlr5AFzlp"}
e:[]
8:"$We"
a:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
f:I[27201,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"IconMark"]
7:null
c:[["$","title","0",{"children":"RentalDriveGo Admin"}],["$","meta","1",{"name":"description","content":"Platform administration for RentalDriveGo."}],["$","link","2",{"rel":"icon","href":"/icon?26e1a3c73d0a3e8c","alt":"$undefined","type":"image/png","sizes":"32x32"}],["$","$Lf","3",{}]]
@@ -0,0 +1,17 @@
1:"$Sreact.fragment"
2:I[51224,["/admin/_next/static/chunks/10txdscg_s8qk.js"],"AdminI18nProvider"]
3:I[39756,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default"]
4:I[37457,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default"]
5:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"OutletBoundary"]
6:"$Sreact.suspense"
9:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"ViewportBoundary"]
b:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"MetadataBoundary"]
d:I[68027,["/admin/_next/static/chunks/10txdscg_s8qk.js"],"default",1]
:HL["/admin/_next/static/chunks/0_wwjs24psu3a.css","style"]
0:{"P":null,"c":["","_not-found"],"q":"","i":false,"f":[[["",{"children":["/_not-found",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/admin/_next/static/chunks/0_wwjs24psu3a.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/admin/_next/static/chunks/10txdscg_s8qk.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"light","suppressHydrationWarning":true,"children":[["$","head",null,{"children":["$","script",null,{"dangerouslySetInnerHTML":{"__html":"(function(){try{var m=document.cookie.match(/(?:^|; )rentaldrivego-theme=([^;]+)/);var theme=m?decodeURIComponent(m[1]):(localStorage.getItem('rentaldrivego-theme')||localStorage.getItem('admin-theme'));if(theme!=='light'&&theme!=='dark'){theme=window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'}document.documentElement.classList.remove('light','dark');document.documentElement.classList.add(theme);document.documentElement.style.colorScheme=theme;document.body&&document.body.setAttribute('data-theme',theme)}catch(e){}})();"}}]}],["$","body",null,{"suppressHydrationWarning":true,"children":["$","$L2",null,{"children":["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L3",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],null,["$","$L5",null,{"children":["$","$6",null,{"name":"Next.MetadataOutlet","children":"$@7"}]}]]}],{},null,false,null]},null,false,"$@8"]},null,false,null],["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L9",null,{"children":"$La"}],["$","div",null,{"hidden":true,"children":["$","$Lb",null,{"children":["$","$6",null,{"name":"Next.Metadata","children":"$Lc"}]}]}],null]}],false]],"m":"$undefined","G":["$d",[["$","link","0",{"rel":"stylesheet","href":"/admin/_next/static/chunks/0_wwjs24psu3a.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"jRlQg50qYlv2hlr5AFzlp"}
e:[]
8:"$We"
a:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
f:I[27201,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"IconMark"]
7:null
c:[["$","title","0",{"children":"RentalDriveGo Admin"}],["$","meta","1",{"name":"description","content":"Platform administration for RentalDriveGo."}],["$","link","2",{"rel":"icon","href":"/icon?26e1a3c73d0a3e8c","alt":"$undefined","type":"image/png","sizes":"32x32"}],["$","$Lf","3",{}]]
@@ -0,0 +1,6 @@
1:"$Sreact.fragment"
2:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"ViewportBoundary"]
3:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"MetadataBoundary"]
4:"$Sreact.suspense"
5:I[27201,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"IconMark"]
0:{"rsc":["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"RentalDriveGo Admin"}],["$","meta","1",{"name":"description","content":"Platform administration for RentalDriveGo."}],["$","link","2",{"rel":"icon","href":"/icon?26e1a3c73d0a3e8c","type":"image/png","sizes":"32x32"}],["$","$L5","3",{}]]}]}]}],null]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"jRlQg50qYlv2hlr5AFzlp"}
@@ -0,0 +1,6 @@
1:"$Sreact.fragment"
2:I[51224,["/admin/_next/static/chunks/10txdscg_s8qk.js"],"AdminI18nProvider"]
3:I[39756,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default"]
4:I[37457,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default"]
:HL["/admin/_next/static/chunks/0_wwjs24psu3a.css","style"]
0:{"rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/admin/_next/static/chunks/0_wwjs24psu3a.css","precedence":"next"}],["$","script","script-0",{"src":"/admin/_next/static/chunks/10txdscg_s8qk.js","async":true}]],["$","html",null,{"lang":"en","className":"light","suppressHydrationWarning":true,"children":[["$","head",null,{"children":["$","script",null,{"dangerouslySetInnerHTML":{"__html":"(function(){try{var m=document.cookie.match(/(?:^|; )rentaldrivego-theme=([^;]+)/);var theme=m?decodeURIComponent(m[1]):(localStorage.getItem('rentaldrivego-theme')||localStorage.getItem('admin-theme'));if(theme!=='light'&&theme!=='dark'){theme=window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light'}document.documentElement.classList.remove('light','dark');document.documentElement.classList.add(theme);document.documentElement.style.colorScheme=theme;document.body&&document.body.setAttribute('data-theme',theme)}catch(e){}})();"}}]}],["$","body",null,{"suppressHydrationWarning":true,"children":["$","$L2",null,{"children":["$","$L3",null,{"parallelRouterKey":"children","template":["$","$L4",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]]}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"jRlQg50qYlv2hlr5AFzlp"}
@@ -0,0 +1,5 @@
1:"$Sreact.fragment"
2:I[39756,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default"]
3:I[37457,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"default"]
4:[]
0:{"rsc":["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}]}]]}],"isPartial":false,"staleTime":300,"varyParams":"$W4","buildId":"jRlQg50qYlv2hlr5AFzlp"}
@@ -0,0 +1,5 @@
1:"$Sreact.fragment"
2:I[97367,["/admin/_next/static/chunks/05-c3ty_6dwfk.js","/admin/_next/static/chunks/18sotvvmcs59d.js"],"OutletBoundary"]
3:"$Sreact.suspense"
0:{"rsc":["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],null,["$","$L2",null,{"children":["$","$3",null,{"name":"Next.MetadataOutlet","children":"$@4"}]}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"jRlQg50qYlv2hlr5AFzlp"}
4:null
@@ -0,0 +1,2 @@
:HL["/admin/_next/static/chunks/0_wwjs24psu3a.css","style"]
0:{"tree":{"name":"","param":null,"prefetchHints":16,"slots":{"children":{"name":"/_not-found","param":null,"prefetchHints":0,"slots":{"children":{"name":"__PAGE__","param":null,"prefetchHints":0,"slots":null}}}}},"staleTime":300,"buildId":"jRlQg50qYlv2hlr5AFzlp"}
@@ -0,0 +1,14 @@
var R=require("../../chunks/ssr/[turbopack]_runtime.js")("server/app/_not-found/page.js")
R.c("server/chunks/ssr/[root-of-the-server]__0ln09ua._.js")
R.c("server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_16dhe4b.js")
R.c("server/chunks/ssr/[root-of-the-server]__1k-d3jf._.js")
R.c("server/chunks/ssr/[root-of-the-server]__0nu24gp._.js")
R.c("server/chunks/ssr/[root-of-the-server]__1rskd5f._.js")
R.c("server/chunks/ssr/_1cx6y-a._.js")
R.c("server/chunks/ssr/apps_admin_src_0ykjik2._.js")
R.c("server/chunks/ssr/node_modules_next_dist_client_components_0wpq8j3._.js")
R.c("server/chunks/ssr/node_modules_next_dist_client_components_builtin_forbidden_0symwr9.js")
R.c("server/chunks/ssr/node_modules_next_dist_client_components_builtin_unauthorized_0l_sp0x.js")
R.c("server/chunks/ssr/apps_admin__next-internal_server_app__not-found_page_actions_158ip1x.js")
R.m(313)
module.exports=R.m(313).exports
@@ -0,0 +1,5 @@
{
"version": 3,
"sources": [],
"sections": []
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
{
"/_not-found/page": "app/_not-found/page.js"
}
@@ -0,0 +1,17 @@
{
"devFiles": [],
"ampDevFiles": [],
"polyfillFiles": [
"static/chunks/0cz1d0mv5g_q7.js"
],
"lowPriorityFiles": [],
"rootMainFiles": [
"static/chunks/3fi7ta8l6_q46.js",
"static/chunks/2de_cmw_l_puw.js",
"static/chunks/3svce10uq2e6q.js",
"static/chunks/40z7xw1jd_fv0.js",
"static/chunks/turbopack-1kvzti-0-yxfi.js"
],
"pages": {},
"ampFirstPages": []
}
@@ -0,0 +1,6 @@
{
"pages": {},
"app": {},
"appUsingSizeAdjust": false,
"pagesUsingSizeAdjust": false
}

Some files were not shown because too many files have changed in this diff Show More