Skip to content

Commit 415a7c0

Browse files
committed
fix(booking): fix booking for deployment
1 parent e54bc3c commit 415a7c0

12 files changed

Lines changed: 139 additions & 49 deletions

File tree

nextjs-autospace/next-env.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/// <reference types="next" />
22
/// <reference types="next/image-types/global" />
3-
import "./.next/dev/types/routes.d.ts";
3+
import "./.next/types/routes.d.ts";
44

55
// NOTE: This file should not be edited
66
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

nextjs-autospace/src/app/(protected)/bookings/page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ export default function MyBookingsPage() {
139139
(b) =>
140140
b.status === "confirmed" ||
141141
b.status === "pending" ||
142-
b.status === "occupied",
142+
b.status === "occupied" ||
143+
b.status === "payment_pending",
143144
);
144145

145146
const historyBookings = bookings.filter(

nextjs-autospace/src/components/garage/GarageDetails.tsx

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -783,17 +783,31 @@ export default function GarageDetails({ garage }: GarageDetailsProps) {
783783
</p>
784784
</div>
785785
</div>
786-
<button
787-
onClick={requestValet}
788-
disabled={!garage.valetAvailable}
789-
className={`px-4 py-1.5 text-[10px] font-black uppercase tracking-wider transition-all ${valetEnabled ? "bg-primary text-gray-900 shadow-md scale-105" : "bg-white border border-gray-200 text-gray-400 hover:text-gray-900"}`}
790-
>
791-
{!garage.valetAvailable
792-
? "Not Available"
793-
: valetEnabled
794-
? "Valet Ready"
795-
: "Check Availability"}
796-
</button>
786+
<div className="flex flex-col items-end gap-1">
787+
<button
788+
onClick={requestValet}
789+
disabled={!garage.valetAvailable}
790+
className={`px-4 py-1.5 text-[10px] font-black uppercase tracking-wider transition-all ${valetEnabled ? "bg-primary text-gray-900 shadow-md scale-105" : "bg-white border border-gray-200 text-gray-400 hover:text-gray-900"}`}
791+
>
792+
{!garage.valetAvailable
793+
? "Not Available"
794+
: valetEnabled
795+
? "Valet Ready"
796+
: "Check Availability"}
797+
</button>
798+
{valetEnabled && (
799+
<button
800+
onClick={() => {
801+
setPickupLocation(null);
802+
setSwiped(false);
803+
setValetState("AVAILABLE");
804+
}}
805+
className="text-[9px] font-black text-red-500 hover:text-red-700 uppercase tracking-tighter underline underline-offset-2"
806+
>
807+
Remove Valet
808+
</button>
809+
)}
810+
</div>
797811
</div>
798812
{!garage.valetAvailable && (
799813
<p className="text-xs text-red-500 font-bold">

nextjs-autospace/src/lib/apiClient.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,21 @@ apiClient.interceptors.response.use(
162162
toast.error("Please login to continue");
163163

164164
if (typeof window !== "undefined") {
165+
const currentPath = window.location.pathname;
166+
const isManagementPath =
167+
currentPath.startsWith("/admin") ||
168+
currentPath.startsWith("/company") ||
169+
currentPath.startsWith("/valet") ||
170+
currentPath.startsWith("/garage") ||
171+
currentPath.startsWith("/dashboard");
172+
173+
const redirectBase = isManagementPath
174+
? "/dashboard/login"
175+
: "/login";
176+
165177
setTimeout(() => {
166178
window.location.href =
167-
"/login?redirect=" + window.location.pathname;
179+
redirectBase + "?redirect=" + window.location.pathname;
168180
}, 3000);
169181
}
170182
}
@@ -195,8 +207,18 @@ apiClient.interceptors.response.use(
195207
toast.error("Your account is not allowed to access this feature");
196208

197209
if (typeof window !== "undefined") {
210+
const currentPath = window.location.pathname;
211+
const isManagementPath =
212+
currentPath.startsWith("/admin") ||
213+
currentPath.startsWith("/company") ||
214+
currentPath.startsWith("/valet") ||
215+
currentPath.startsWith("/garage") ||
216+
currentPath.startsWith("/dashboard");
217+
218+
const redirectBase = isManagementPath ? "/dashboard/login" : "/login";
219+
198220
setTimeout(() => {
199-
window.location.href = "/login?reason=rejected";
221+
window.location.href = `${redirectBase}?reason=rejected`;
200222
}, 3000);
201223
}
202224

nextjs-autospace/src/lib/auth.api.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,18 @@ export const getMe = () => {
8585
};
8686

8787
export const logoutUser = async (): Promise<void> => {
88+
const currentPath =
89+
typeof window !== "undefined" ? window.location.pathname : "";
90+
const isManagementPath =
91+
currentPath.startsWith("/admin") ||
92+
currentPath.startsWith("/company") ||
93+
currentPath.startsWith("/valet") ||
94+
currentPath.startsWith("/garage") ||
95+
currentPath.startsWith("/dashboard");
96+
8897
try {
8998
await apiClient.post("/api/auth/logout");
9099
} finally {
91-
window.location.href = "/login";
100+
window.location.href = isManagementPath ? "/dashboard/login" : "/login";
92101
}
93102
};

nextjs-autospace/src/middleware/middleware.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,15 @@ export function middleware(req: NextRequest) {
1212
"/garage",
1313
];
1414

15-
const isProtected = protectedRoutes.some((route) =>
16-
req.nextUrl.pathname.startsWith(route),
17-
);
15+
const isProtected = protectedRoutes.some((route) => {
16+
if (route === "/garage") {
17+
return (
18+
req.nextUrl.pathname === "/garage" ||
19+
req.nextUrl.pathname.startsWith("/garage/")
20+
);
21+
}
22+
return req.nextUrl.pathname.startsWith(route);
23+
});
1824

1925
// Not logged in → block access
2026
if (isProtected && !accessToken) {

nodejs-autospace/api-gateway/dist/index.js

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,47 +12,45 @@ const cookie_parser_1 = __importDefault(require("cookie-parser"));
1212
const auth_proxy_1 = __importDefault(require("./routes/auth.proxy"));
1313
const healthcheck_1 = require("./utils/healthcheck");
1414
const resource_proxy_1 = __importDefault(require("./routes/resource.proxy"));
15+
const logger_1 = require("@autospace/logger");
1516
const booking_proxy_1 = __importDefault(require("./routes/booking.proxy"));
1617
const app = (0, express_1.default)();
18+
const logger = (0, logger_1.createLogger)({ service: "api-gateway" });
19+
const httpLogger = (0, logger_1.createHttpLogger)({ service: "api-gateway" });
20+
app.use(httpLogger);
1721
const port = process.env.GATEWAY_PORT || 4000;
1822
app.use((0, helmet_1.default)());
23+
app.use((0, cors_1.default)({
24+
origin: process.env.FRONTEND_URL,
25+
credentials: true,
26+
methods: ["GET", "POST", "PUT", "DELETE", "PATCH"],
27+
allowedHeaders: ["Content-Type", "Authorization", "x-user-id", "x-role"],
28+
}));
29+
// in local commend that here change on lacal
30+
// const allowedOrigins = [
31+
// "https://autospace.space",
32+
// "https://www.autospace.space",
33+
// ];
1934
// app.use(
2035
// cors({
21-
// origin: process.env.FRONTEND_URL!,
36+
// origin: (origin, callback) => {
37+
// if (!origin) return callback(null, true);
38+
// if (allowedOrigins.includes(origin)) {
39+
// return callback(null, origin);
40+
// }
41+
// logger.warn(`Blocked by CORS: ${origin}`);
42+
// return callback(new Error("Not allowed by CORS"));
43+
// },
2244
// credentials: true,
23-
// methods: ["GET", "POST", "PUT", "DELETE", "PATCH"],
24-
// allowedHeaders: ["Content-Type", "Authorization", "x-user-id", "x-role"],
2545
// }),
2646
// );
27-
// in local commend that here change on lacal
28-
const allowedOrigins = [
29-
"https://autospace.space",
30-
"https://www.autospace.space",
31-
];
32-
app.set("trust proxy", 1);
33-
app.use((0, cors_1.default)({
34-
origin: (origin, callback) => {
35-
if (!origin)
36-
return callback(null, true);
37-
if (allowedOrigins.includes(origin)) {
38-
return callback(null, true);
39-
}
40-
console.log(" Blocked by CORS:", origin);
41-
return callback(null, false);
42-
},
43-
credentials: true,
44-
}));
45-
console.log("AUTH_SERVICE_URL =", process.env.AUTH_SERVICE_URL);
47+
logger.info(`AUTH_SERVICE_URL = ${process.env.AUTH_SERVICE_URL}`);
4648
app.use(express_1.default.json());
4749
app.use(express_1.default.urlencoded({ extended: true }));
4850
app.use((0, cookie_parser_1.default)());
4951
app.get("/debug-cookies", (req, res) => {
5052
res.json(req.cookies);
5153
});
52-
app.use((req, res, next) => {
53-
console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);
54-
next();
55-
});
5654
app.get("/health", (req, res) => {
5755
res.json({
5856
status: "ok",
@@ -79,7 +77,18 @@ app.use((req, res) => {
7977
});
8078
});
8179
app.listen(port, () => {
82-
console.log(`server running on port ${port}`);
83-
console.log("the health check on ");
80+
logger.info(`server running on port ${port}`);
81+
logger.info("the health check on ");
82+
});
83+
app.use((err, req, res, next) => {
84+
logger.error("Unhandled error", {
85+
message: err.message,
86+
stack: err.stack,
87+
path: req.path,
88+
});
89+
res.status(500).json({
90+
success: false,
91+
message: "Internal server error",
92+
});
8493
});
8594
exports.default = app;

nodejs-autospace/api-gateway/src/routes/resource.proxy.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ router.use(
174174

175175
router.use(
176176
"/files",
177-
authMiddleware,
178177
createProxyMiddleware({
179178
target: RESOURCE_SERVICE_URL,
180179
changeOrigin: true,

nodejs-autospace/booking-service/src/controllers/webhook.controller.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Booking } from "../entities/booking.entity.js";
55
import { Payment, PaymentStatus } from "../entities/payment.entity.js";
66
import { BookingService } from "../services/booking.service.js";
77
import { logger } from "../utils/logger.js";
8+
import redisClient from "../config/redis.js";
89

910
// Stripe, repo and service initialized inside handler
1011

@@ -103,6 +104,14 @@ export const stripeWebhookController = async (req: Request, res: Response) => {
103104
},
104105
);
105106

107+
// Invalidate user booking list cache
108+
if (updatedBooking) {
109+
await redisClient.del(`userBookings:v2:${updatedBooking.userId}`);
110+
logger.info("Invalidated user bookings cache after payment", {
111+
userId: updatedBooking.userId,
112+
});
113+
}
114+
106115
// AFTER transaction
107116
if (updatedBooking && updatedBooking.valetRequested) {
108117
try {

nodejs-autospace/resource-service/dist/db/data-source.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ exports.AppDataSource = new typeorm_1.DataSource({
1111
},
1212
synchronize: false,
1313
logging: true,
14-
entities: [__dirname + "/../modules/**/*.entity.ts"],
14+
entities: [__dirname + "/../modules/**/*.entity.js"],
1515
});
1616
setInterval(async () => {
1717
await exports.AppDataSource.query("SELECT 1");

0 commit comments

Comments
 (0)