first after 100
This commit is contained in:
parent
b1472a7f72
commit
cb0960299d
@ -8,7 +8,7 @@ import Toast from "~/components/Toast";
|
||||
import { useState, useEffect } from "react";
|
||||
import { prisma } from "~/utils/db.server";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "Areas Management - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Areas Management - Alhaffer Report System" }];
|
||||
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const user = await requireAuthLevel(request, 2);
|
||||
|
||||
@ -5,7 +5,7 @@ import { requireAuthLevel } from "~/utils/auth.server";
|
||||
import DashboardLayout from "~/components/DashboardLayout";
|
||||
import { prisma } from "~/utils/db.server";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "Dashboard - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Dashboard - Alhaffer Report System" }];
|
||||
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const user = await requireAuthLevel(request, 1);
|
||||
@ -51,7 +51,7 @@ export default function Dashboard() {
|
||||
Welcome back, {user.name}!
|
||||
</h2>
|
||||
<p className="text-sm sm:text-base text-gray-600">
|
||||
Here's what's happening with your phosphat operations today.
|
||||
Here's what's happening with your allhaffer operations today.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -8,7 +8,7 @@ import Toast from "~/components/Toast";
|
||||
import { useState, useEffect } from "react";
|
||||
import { prisma } from "~/utils/db.server";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "Dredger Locations Management - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Dredger Locations Management - Alhaffer Report System" }];
|
||||
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const user = await requireAuthLevel(request, 2);
|
||||
|
||||
@ -9,7 +9,7 @@ import { useState, useEffect } from "react";
|
||||
import bcrypt from "bcryptjs";
|
||||
import { prisma } from "~/utils/db.server";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "Employee Management - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Employee Management - Alhaffer Report System" }];
|
||||
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const user = await requireAuthLevel(request, 2);
|
||||
|
||||
@ -8,7 +8,7 @@ import Toast from "~/components/Toast";
|
||||
import { useState, useEffect } from "react";
|
||||
import { prisma } from "~/utils/db.server";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "Equipment Management - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Equipment Management - Alhaffer Report System" }];
|
||||
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const user = await requireAuthLevel(request, 2);
|
||||
|
||||
@ -8,7 +8,7 @@ import Toast from "~/components/Toast";
|
||||
import { useState, useEffect } from "react";
|
||||
import { prisma } from "~/utils/db.server";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "Foreman Management - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Foreman Management - Alhaffer Report System" }];
|
||||
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const user = await requireAuthLevel(request, 2);
|
||||
|
||||
@ -8,7 +8,7 @@ import Toast from "~/components/Toast";
|
||||
import { useState, useEffect } from "react";
|
||||
import { prisma } from "~/utils/db.server";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "Reclamation Locations Management - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Reclamation Locations Management - Alhaffer Report System" }];
|
||||
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const user = await requireAuthLevel(request, 2);
|
||||
|
||||
@ -7,7 +7,7 @@ import ReportSheetViewModal from "~/components/ReportSheetViewModal";
|
||||
import { useState } from "react";
|
||||
import { prisma } from "~/utils/db.server";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "Report Sheets - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Report Sheets - Alhaffer Report System" }];
|
||||
|
||||
interface ReportSheet {
|
||||
id: string;
|
||||
|
||||
@ -10,7 +10,7 @@ import { useState, useEffect } from "react";
|
||||
import { manageSheet, removeFromSheet } from "~/utils/sheet.server";
|
||||
import { prisma } from "~/utils/db.server";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "Reports Management - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Reports Management - Alhaffer Report System" }];
|
||||
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const user = await requireAuthLevel(request, 1); // All employees can access reports
|
||||
|
||||
@ -6,7 +6,7 @@ import DashboardLayout from "~/components/DashboardLayout";
|
||||
import { useState, useEffect } from "react";
|
||||
import { prisma } from "~/utils/db.server";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "Edit Report - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Edit Report - Alhaffer Report System" }];
|
||||
|
||||
export const loader = async ({ request, params }: LoaderFunctionArgs) => {
|
||||
const user = await requireAuthLevel(request, 1);
|
||||
@ -112,6 +112,7 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
|
||||
const statsExc = formData.get("statsExc");
|
||||
const statsLoaders = formData.get("statsLoaders");
|
||||
const statsForeman = formData.get("statsForeman");
|
||||
const statsLaborer = formData.get("statsLaborer");
|
||||
const workersListData = formData.get("workersList");
|
||||
const timeSheetData = formData.get("timeSheetData");
|
||||
const stoppagesData = formData.get("stoppagesData");
|
||||
@ -149,7 +150,7 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
|
||||
let finalNotes = typeof notes === "string" ? notes : '';
|
||||
if (automaticNotes.length > 0) {
|
||||
const automaticNotesText = automaticNotes.join(', ');
|
||||
finalNotes = finalNotes.trim() ? `${automaticNotesText}. ${finalNotes}` : automaticNotesText;
|
||||
finalNotes = finalNotes.trim() ? `${automaticNotesText}.\n${finalNotes}` : automaticNotesText;
|
||||
}
|
||||
|
||||
await prisma.report.update({
|
||||
@ -172,7 +173,7 @@ export const action = async ({ request, params }: ActionFunctionArgs) => {
|
||||
Exc: parseInt(statsExc as string) || 0,
|
||||
Loaders: parseInt(statsLoaders as string) || 0,
|
||||
Foreman: statsForeman as string || "",
|
||||
Laborer: workersList.length
|
||||
Laborer: parseInt(statsLaborer as string) || 0
|
||||
},
|
||||
timeSheet,
|
||||
stoppages,
|
||||
@ -222,6 +223,7 @@ export default function EditReport() {
|
||||
report.shiftWorkers?.map((sw: any) => sw.worker.id) || []
|
||||
);
|
||||
const [workerSearchTerm, setWorkerSearchTerm] = useState('');
|
||||
const [isLaborerManuallyEdited, setIsLaborerManuallyEdited] = useState(false);
|
||||
|
||||
const [timeSheetEntries, setTimeSheetEntries] = useState<Array<{
|
||||
id: string,
|
||||
@ -467,6 +469,16 @@ export default function EditReport() {
|
||||
return true; // All steps are optional for editing
|
||||
};
|
||||
|
||||
// Auto-update laborer count when workers change (only if not manually edited)
|
||||
useEffect(() => {
|
||||
if (!isLaborerManuallyEdited) {
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
statsLaborer: selectedWorkers.length.toString()
|
||||
}));
|
||||
}
|
||||
}, [selectedWorkers, isLaborerManuallyEdited]);
|
||||
|
||||
// Worker selection functions
|
||||
const toggleWorker = (workerId: number) => {
|
||||
setSelectedWorkers(prev =>
|
||||
@ -762,10 +774,13 @@ export default function EditReport() {
|
||||
id="statsLaborer"
|
||||
name="statsLaborer"
|
||||
min="0"
|
||||
value={selectedWorkers.length}
|
||||
readOnly
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-gray-100 text-gray-700 cursor-not-allowed"
|
||||
title="Auto-calculated based on selected workers"
|
||||
value={formData.statsLaborer}
|
||||
onChange={(e) => {
|
||||
updateFormData('statsLaborer', e.target.value);
|
||||
setIsLaborerManuallyEdited(true);
|
||||
}}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500"
|
||||
title="Auto-calculated based on selected workers, but can be edited"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -1169,6 +1184,7 @@ export default function EditReport() {
|
||||
<input type="hidden" name="statsExc" value={formData.statsExc} />
|
||||
<input type="hidden" name="statsLoaders" value={formData.statsLoaders} />
|
||||
<input type="hidden" name="statsForeman" value={formData.statsForeman} />
|
||||
<input type="hidden" name="statsLaborer" value={formData.statsLaborer} />
|
||||
</>
|
||||
)}
|
||||
{currentStep !== 3 && (
|
||||
|
||||
@ -7,7 +7,7 @@ import { useState, useEffect } from "react";
|
||||
import { manageSheet } from "~/utils/sheet.server";
|
||||
import { prisma } from "~/utils/db.server";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "New Report - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "New Report - Alhaffer Report System" }];
|
||||
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const user = await requireAuthLevel(request, 1); // All employees can create reports
|
||||
@ -144,7 +144,7 @@ export const action = async ({ request }: ActionFunctionArgs) => {
|
||||
if (automaticNotes.length > 0) {
|
||||
const automaticNotesText = automaticNotes.join(', ');
|
||||
if (finalNotes.trim()) {
|
||||
finalNotes = `${automaticNotesText}. ${finalNotes}`;
|
||||
finalNotes = `${automaticNotesText}.\n${finalNotes}`;
|
||||
} else {
|
||||
finalNotes = automaticNotesText;
|
||||
}
|
||||
@ -178,7 +178,7 @@ export const action = async ({ request }: ActionFunctionArgs) => {
|
||||
Exc: parseInt(statsExc as string) || 0,
|
||||
Loaders: parseInt(statsLoaders as string) || 0,
|
||||
Foreman: statsForeman as string || "",
|
||||
Laborer: workersList.length
|
||||
Laborer: parseInt(statsLaborer as string) || 0
|
||||
},
|
||||
timeSheet,
|
||||
stoppages,
|
||||
@ -241,6 +241,8 @@ export default function NewReport() {
|
||||
notes: ''
|
||||
});
|
||||
|
||||
const [isLaborerManuallyEdited, setIsLaborerManuallyEdited] = useState(false);
|
||||
|
||||
const [validationError, setValidationError] = useState<string | null>(null);
|
||||
const [selectedWorkers, setSelectedWorkers] = useState<number[]>([]);
|
||||
const [workerSearchTerm, setWorkerSearchTerm] = useState('');
|
||||
@ -641,6 +643,16 @@ export default function NewReport() {
|
||||
}
|
||||
};
|
||||
|
||||
// Auto-update laborer count when workers change (only if not manually edited)
|
||||
useEffect(() => {
|
||||
if (!isLaborerManuallyEdited) {
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
statsLaborer: selectedWorkers.length.toString()
|
||||
}));
|
||||
}
|
||||
}, [selectedWorkers, isLaborerManuallyEdited]);
|
||||
|
||||
// Worker selection functions
|
||||
const toggleWorker = (workerId: number) => {
|
||||
setSelectedWorkers(prev =>
|
||||
@ -909,7 +921,10 @@ export default function NewReport() {
|
||||
<div><label htmlFor="statsExc" className="block text-sm font-medium text-gray-700 mb-2">Excavators <span className="text-xs text-gray-500">(Auto-calculated)</span></label><input type="number" id="statsExc" name="statsExc" min="0" value={formData.statsExc} readOnly className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-gray-100 text-gray-700 cursor-not-allowed" title="Auto-calculated based on time sheet entries" /></div>
|
||||
<div><label htmlFor="statsLoaders" className="block text-sm font-medium text-gray-700 mb-2">Loaders <span className="text-xs text-gray-500">(Auto-calculated)</span></label><input type="number" id="statsLoaders" name="statsLoaders" min="0" value={formData.statsLoaders} readOnly className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-gray-100 text-gray-700 cursor-not-allowed" title="Auto-calculated based on time sheet entries" /></div>
|
||||
<div><label htmlFor="statsForeman" className="block text-sm font-medium text-gray-700 mb-2">Foreman</label><select id="statsForeman" name="statsForeman" value={formData.statsForeman} onChange={(e) => updateFormData('statsForeman', e.target.value)} className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500"><option value="">Select foreman</option>{foremen.map((foreman) => (<option key={foreman.id} value={foreman.name}>{foreman.name}</option>))}</select></div>
|
||||
<div><label htmlFor="statsLaborer" className="block text-sm font-medium text-gray-700 mb-2">Laborers <span className="text-xs text-gray-500">({selectedWorkers.length} selected)</span></label><input type="number" id="statsLaborer" name="statsLaborer" min="0" value={selectedWorkers.length} readOnly className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-gray-100 text-gray-700 cursor-not-allowed" title="Auto-calculated based on selected workers" /></div>
|
||||
<div><label htmlFor="statsLaborer" className="block text-sm font-medium text-gray-700 mb-2">Laborers <span className="text-xs text-gray-500">({selectedWorkers.length} selected)</span></label><input type="number" id="statsLaborer" name="statsLaborer" min="0" value={formData.statsLaborer} onChange={(e) => {
|
||||
updateFormData('statsLaborer', e.target.value);
|
||||
setIsLaborerManuallyEdited(true);
|
||||
}} className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500" title="Auto-calculated based on selected workers, but can be edited" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@ -3,7 +3,7 @@ import { json, redirect } from "@remix-run/node";
|
||||
import { Form, Link, useActionData, useSearchParams } from "@remix-run/react";
|
||||
import { createUserSession, getUserId, verifyLogin } from "~/utils/auth.server";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "Sign In - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Sign In - Alhaffer Report System" }];
|
||||
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const userId = await getUserId(request);
|
||||
|
||||
@ -4,7 +4,7 @@ import { Form, Link, useActionData } from "@remix-run/react";
|
||||
import { createUser, createUserSession, getUserId } from "~/utils/auth.server";
|
||||
import { prisma } from "~/utils/db.server";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "Sign Up - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Sign Up - Alhaffer Report System" }];
|
||||
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const userId = await getUserId(request);
|
||||
|
||||
@ -6,7 +6,7 @@ import DashboardLayout from "~/components/DashboardLayout";
|
||||
import { useState } from "react";
|
||||
import { prisma } from "~/utils/db.server";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "Stoppages Analysis - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Stoppages Analysis - Alhaffer Report System" }];
|
||||
|
||||
interface StoppageEntry {
|
||||
id: string;
|
||||
|
||||
@ -7,7 +7,7 @@ import { useState, useEffect } from "react";
|
||||
import { prisma } from "~/utils/db.server";
|
||||
import Toast from "~/components/Toast";
|
||||
|
||||
export const meta: MetaFunction = () => [{ title: "Workers - Phosphat Report" }];
|
||||
export const meta: MetaFunction = () => [{ title: "Workers - Alhaffer Report System" }];
|
||||
|
||||
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
||||
const user = await requireAuthLevel(request, 2); // Only supervisors and admins
|
||||
|
||||
BIN
prisma/dev.db
BIN
prisma/dev.db
Binary file not shown.
Loading…
Reference in New Issue
Block a user