🎯 MapView v2.0 - Global Deployment Ready

 MAJOR FEATURES:
• Auto-zoom intelligence với smart bounds fitting
• Enhanced 3D GPS markers với pulsing effects
• Professional route display với 6-layer rendering
• Status-based parking icons với availability indicators
• Production-ready build optimizations

🗺️ AUTO-ZOOM FEATURES:
• Smart bounds fitting cho GPS + selected parking
• Adaptive padding (50px) cho visual balance
• Max zoom control (level 16) để tránh quá gần
• Dynamic centering khi không có selection

🎨 ENHANCED VISUALS:
• 3D GPS marker với multi-layer pulse effects
• Advanced parking icons với status colors
• Selection highlighting với animation
• Dimming system cho non-selected items

🛣️ ROUTE SYSTEM:
• OpenRouteService API integration
• Multi-layer route rendering (glow, shadow, main, animated)
• Real-time distance & duration calculation
• Visual route info trong popup

📱 PRODUCTION READY:
• SSR safe với dynamic imports
• Build errors resolved
• Global deployment via Vercel
• Optimized performance

🌍 DEPLOYMENT:
• Vercel: https://whatever-ctk2auuxr-phong12hexdockworks-projects.vercel.app
• Bundle size: 22.8 kB optimized
• Global CDN distribution
• HTTPS enabled

💾 VERSION CONTROL:
• MapView-v2.0.tsx backup created
• MAPVIEW_VERSIONS.md documentation
• Full version history tracking
This commit is contained in:
2025-07-20 19:52:16 +07:00
parent 3203463a6a
commit c65cc97a33
64624 changed files with 7199453 additions and 6462 deletions

View File

@@ -0,0 +1,54 @@
export interface IStreamReader {
/**
* Peak ahead (peek) from stream. Subsequent read or peeks will return the same data.
* @param uint8Array - Uint8Array (or Buffer) to store data read from stream in
* @param mayBeLess - Allow the read to complete, without the buffer being fully filled (length may be smaller)
* @returns Number of bytes peeked. If `maybeLess` is set, this shall be the `uint8Array.length`.
*/
peek(uint8Array: Uint8Array, mayBeLess?: boolean): Promise<number>;
/**
* Read from stream the stream.
* @param uint8Array - Uint8Array (or Buffer) to store data read from stream in
* @param mayBeLess - Allow the read to complete, without the buffer being fully filled (length may be smaller)
* @returns Number of actually bytes read. If `maybeLess` is set, this shall be the `uint8Array.length`.
*/
read(uint8Array: Uint8Array, mayBeLess?: boolean): Promise<number>;
close(): Promise<void>;
/**
* Abort any active asynchronous operation are active, abort those before they may have completed.
*/
abort(): Promise<void>;
}
export declare abstract class AbstractStreamReader implements IStreamReader {
protected endOfStream: boolean;
protected interrupted: boolean;
/**
* Store peeked data
* @type {Array}
*/
protected peekQueue: Uint8Array[];
peek(uint8Array: Uint8Array, mayBeLess?: boolean): Promise<number>;
read(buffer: Uint8Array, mayBeLess?: boolean): Promise<number>;
/**
* Read chunk from stream
* @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
* @returns Number of bytes read
*/
protected readFromPeekBuffer(buffer: Uint8Array): number;
readRemainderFromStream(buffer: Uint8Array, mayBeLess: boolean): Promise<number>;
/**
* Read from stream
* @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
* @param mayBeLess - If true, may fill the buffer partially
* @protected Bytes read
*/
protected abstract readFromStream(buffer: Uint8Array, mayBeLess: boolean): Promise<number>;
/**
* abort synchronous operations
*/
abstract close(): Promise<void>;
/**
* Abort any active asynchronous operation are active, abort those before they may have completed.
*/
abstract abort(): Promise<void>;
}

View File

@@ -0,0 +1,71 @@
import { EndOfStreamError, AbortError } from "./Errors.js";
export class AbstractStreamReader {
constructor() {
this.endOfStream = false;
this.interrupted = false;
/**
* Store peeked data
* @type {Array}
*/
this.peekQueue = [];
}
async peek(uint8Array, mayBeLess = false) {
const bytesRead = await this.read(uint8Array, mayBeLess);
this.peekQueue.push(uint8Array.subarray(0, bytesRead)); // Put read data back to peek buffer
return bytesRead;
}
async read(buffer, mayBeLess = false) {
if (buffer.length === 0) {
return 0;
}
let bytesRead = this.readFromPeekBuffer(buffer);
if (!this.endOfStream) {
bytesRead += await this.readRemainderFromStream(buffer.subarray(bytesRead), mayBeLess);
}
if (bytesRead === 0 && !mayBeLess) {
throw new EndOfStreamError();
}
return bytesRead;
}
/**
* Read chunk from stream
* @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
* @returns Number of bytes read
*/
readFromPeekBuffer(buffer) {
let remaining = buffer.length;
let bytesRead = 0;
// consume peeked data first
while (this.peekQueue.length > 0 && remaining > 0) {
const peekData = this.peekQueue.pop(); // Front of queue
if (!peekData)
throw new Error('peekData should be defined');
const lenCopy = Math.min(peekData.length, remaining);
buffer.set(peekData.subarray(0, lenCopy), bytesRead);
bytesRead += lenCopy;
remaining -= lenCopy;
if (lenCopy < peekData.length) {
// remainder back to queue
this.peekQueue.push(peekData.subarray(lenCopy));
}
}
return bytesRead;
}
async readRemainderFromStream(buffer, mayBeLess) {
let bytesRead = 0;
// Continue reading from stream if required
while (bytesRead < buffer.length && !this.endOfStream) {
if (this.interrupted) {
throw new AbortError();
}
const chunkLen = await this.readFromStream(buffer.subarray(bytesRead), mayBeLess);
if (chunkLen === 0)
break;
bytesRead += chunkLen;
}
if (!mayBeLess && bytesRead < buffer.length) {
throw new EndOfStreamError();
}
return bytesRead;
}
}

View File

@@ -0,0 +1,6 @@
export declare class Deferred<T> {
promise: Promise<T>;
resolve: (value: T) => void;
reject: (reason: Error) => void;
constructor();
}

10
backend/node_modules/strtok3/lib/stream/Deferred.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
export class Deferred {
constructor() {
this.resolve = () => null;
this.reject = () => null;
this.promise = new Promise((resolve, reject) => {
this.reject = reject;
this.resolve = resolve;
});
}
}

10
backend/node_modules/strtok3/lib/stream/Errors.d.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
export declare const defaultMessages = "End-Of-Stream";
/**
* Thrown on read operation of the end of file or stream has been reached
*/
export declare class EndOfStreamError extends Error {
constructor();
}
export declare class AbortError extends Error {
constructor(message?: string);
}

16
backend/node_modules/strtok3/lib/stream/Errors.js generated vendored Normal file
View File

@@ -0,0 +1,16 @@
export const defaultMessages = 'End-Of-Stream';
/**
* Thrown on read operation of the end of file or stream has been reached
*/
export class EndOfStreamError extends Error {
constructor() {
super(defaultMessages);
this.name = "EndOfStreamError";
}
}
export class AbortError extends Error {
constructor(message = "The operation was aborted") {
super(message);
this.name = "AbortError";
}
}

View File

@@ -0,0 +1,29 @@
import type { Readable } from 'node:stream';
import { AbstractStreamReader } from "./AbstractStreamReader.js";
/**
* Node.js Readable Stream Reader
* Ref: https://nodejs.org/api/stream.html#readable-streams
*/
export declare class StreamReader extends AbstractStreamReader {
private s;
/**
* Deferred used for postponed read request (as not data is yet available to read)
*/
private deferred;
constructor(s: Readable);
/**
* Read chunk from stream
* @param buffer Target Uint8Array (or Buffer) to store data read from stream in
* @param mayBeLess - If true, may fill the buffer partially
* @returns Number of bytes read
*/
protected readFromStream(buffer: Uint8Array, mayBeLess: boolean): Promise<number>;
/**
* Process deferred read request
* @param request Deferred read request
*/
private readDeferred;
private reject;
abort(): Promise<void>;
close(): Promise<void>;
}

View File

@@ -0,0 +1,83 @@
import { AbortError, } from './Errors.js';
import { Deferred } from './Deferred.js';
import { AbstractStreamReader } from "./AbstractStreamReader.js";
/**
* Node.js Readable Stream Reader
* Ref: https://nodejs.org/api/stream.html#readable-streams
*/
export class StreamReader extends AbstractStreamReader {
constructor(s) {
super();
this.s = s;
/**
* Deferred used for postponed read request (as not data is yet available to read)
*/
this.deferred = null;
if (!s.read || !s.once) {
throw new Error('Expected an instance of stream.Readable');
}
this.s.once('end', () => {
this.endOfStream = true;
if (this.deferred) {
this.deferred.resolve(0);
}
});
this.s.once('error', err => this.reject(err));
this.s.once('close', () => this.abort());
}
/**
* Read chunk from stream
* @param buffer Target Uint8Array (or Buffer) to store data read from stream in
* @param mayBeLess - If true, may fill the buffer partially
* @returns Number of bytes read
*/
async readFromStream(buffer, mayBeLess) {
if (buffer.length === 0)
return 0;
const readBuffer = this.s.read(buffer.length);
if (readBuffer) {
buffer.set(readBuffer);
return readBuffer.length;
}
const request = {
buffer,
mayBeLess,
deferred: new Deferred()
};
this.deferred = request.deferred;
this.s.once('readable', () => {
this.readDeferred(request);
});
return request.deferred.promise;
}
/**
* Process deferred read request
* @param request Deferred read request
*/
readDeferred(request) {
const readBuffer = this.s.read(request.buffer.length);
if (readBuffer) {
request.buffer.set(readBuffer);
request.deferred.resolve(readBuffer.length);
this.deferred = null;
}
else {
this.s.once('readable', () => {
this.readDeferred(request);
});
}
}
reject(err) {
this.interrupted = true;
if (this.deferred) {
this.deferred.reject(err);
this.deferred = null;
}
}
async abort() {
this.reject(new AbortError());
}
async close() {
return this.abort();
}
}

View File

@@ -0,0 +1,14 @@
import { WebStreamReader } from './WebStreamReader.js';
/**
* Read from a WebStream using a BYOB reader
* Reference: https://nodejs.org/api/webstreams.html#class-readablestreambyobreader
*/
export declare class WebStreamByobReader extends WebStreamReader {
/**
* Read from stream
* @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
* @param mayBeLess - If true, may fill the buffer partially
* @protected Bytes read
*/
protected readFromStream(buffer: Uint8Array, mayBeLess: boolean): Promise<number>;
}

View File

@@ -0,0 +1,27 @@
import { WebStreamReader } from './WebStreamReader.js';
/**
* Read from a WebStream using a BYOB reader
* Reference: https://nodejs.org/api/webstreams.html#class-readablestreambyobreader
*/
export class WebStreamByobReader extends WebStreamReader {
/**
* Read from stream
* @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
* @param mayBeLess - If true, may fill the buffer partially
* @protected Bytes read
*/
async readFromStream(buffer, mayBeLess) {
if (buffer.length === 0)
return 0;
// @ts-ignore
const result = await this.reader.read(new Uint8Array(buffer.length), { min: mayBeLess ? undefined : buffer.length });
if (result.done) {
this.endOfStream = result.done;
}
if (result.value) {
buffer.set(result.value);
return result.value.length;
}
return 0;
}
}

View File

@@ -0,0 +1,19 @@
import { AbstractStreamReader } from "./AbstractStreamReader.js";
export declare class WebStreamDefaultReader extends AbstractStreamReader {
private reader;
private buffer;
constructor(reader: ReadableStreamDefaultReader<Uint8Array>);
/**
* Copy chunk to target, and store the remainder in this.buffer
*/
private writeChunk;
/**
* Read from stream
* @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
* @param mayBeLess - If true, may fill the buffer partially
* @protected Bytes read
*/
protected readFromStream(buffer: Uint8Array, mayBeLess: boolean): Promise<number>;
abort(): Promise<void>;
close(): Promise<void>;
}

View File

@@ -0,0 +1,62 @@
import { EndOfStreamError } from './Errors.js';
import { AbstractStreamReader } from "./AbstractStreamReader.js";
export class WebStreamDefaultReader extends AbstractStreamReader {
constructor(reader) {
super();
this.reader = reader;
this.buffer = null; // Internal buffer to store excess data
}
/**
* Copy chunk to target, and store the remainder in this.buffer
*/
writeChunk(target, chunk) {
const written = Math.min(chunk.length, target.length);
target.set(chunk.subarray(0, written));
// Adjust the remainder of the buffer
if (written < chunk.length) {
this.buffer = chunk.subarray(written);
}
else {
this.buffer = null;
}
return written;
}
/**
* Read from stream
* @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
* @param mayBeLess - If true, may fill the buffer partially
* @protected Bytes read
*/
async readFromStream(buffer, mayBeLess) {
if (buffer.length === 0)
return 0;
let totalBytesRead = 0;
// Serve from the internal buffer first
if (this.buffer) {
totalBytesRead += this.writeChunk(buffer, this.buffer);
}
// Continue reading from the stream if more data is needed
while (totalBytesRead < buffer.length && !this.endOfStream) {
const result = await this.reader.read();
if (result.done) {
this.endOfStream = true;
break;
}
if (result.value) {
totalBytesRead += this.writeChunk(buffer.subarray(totalBytesRead), result.value);
}
}
if (!mayBeLess && totalBytesRead === 0 && this.endOfStream) {
throw new EndOfStreamError();
}
return totalBytesRead;
}
abort() {
this.interrupted = true;
return this.reader.cancel();
}
async close() {
await this.abort();
this.reader.releaseLock();
}
}

View File

@@ -0,0 +1,14 @@
import { AbstractStreamReader } from "./AbstractStreamReader.js";
export declare abstract class WebStreamReader extends AbstractStreamReader {
protected reader: ReadableStreamDefaultReader | ReadableStreamBYOBReader;
constructor(reader: ReadableStreamDefaultReader | ReadableStreamBYOBReader);
/**
* Read from stream
* @param buffer - Target Uint8Array (or Buffer) to store data read from stream in
* @param mayBeLess - If true, may fill the buffer partially
* @protected Bytes read
*/
protected abstract readFromStream(buffer: Uint8Array, mayBeLess: boolean): Promise<number>;
abort(): Promise<void>;
close(): Promise<void>;
}

View File

@@ -0,0 +1,13 @@
import { AbstractStreamReader } from "./AbstractStreamReader.js";
export class WebStreamReader extends AbstractStreamReader {
constructor(reader) {
super();
this.reader = reader;
}
async abort() {
return this.close();
}
async close() {
this.reader.releaseLock();
}
}

View File

@@ -0,0 +1,5 @@
import type { ReadableStream as NodeReadableStream } from 'node:stream/web';
import { WebStreamByobReader } from './WebStreamByobReader.js';
import { WebStreamDefaultReader } from './WebStreamDefaultReader.js';
export type AnyWebByteStream = NodeReadableStream<Uint8Array> | ReadableStream<Uint8Array>;
export declare function makeWebStreamReader(stream: AnyWebByteStream): WebStreamByobReader | WebStreamDefaultReader;

View File

@@ -0,0 +1,19 @@
import { WebStreamByobReader } from './WebStreamByobReader.js';
import { WebStreamDefaultReader } from './WebStreamDefaultReader.js';
export function makeWebStreamReader(stream) {
try {
const reader = stream.getReader({ mode: "byob" });
if (reader instanceof ReadableStreamDefaultReader) {
// Fallback to default reader in case `mode: byob` is ignored
return new WebStreamDefaultReader(reader);
}
return new WebStreamByobReader(reader);
}
catch (error) {
if (error instanceof TypeError) {
// Fallback to default reader in case `mode: byob` rejected by a `TypeError`
return new WebStreamDefaultReader(stream.getReader());
}
throw error;
}
}

6
backend/node_modules/strtok3/lib/stream/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,6 @@
export { AbortError, EndOfStreamError } from './Errors.js';
export { StreamReader } from './StreamReader.js';
export { WebStreamByobReader } from './WebStreamByobReader.js';
export { WebStreamDefaultReader } from './WebStreamDefaultReader.js';
export type { IStreamReader } from './AbstractStreamReader.js';
export { type AnyWebByteStream, makeWebStreamReader } from './WebStreamReaderFactory.js';

5
backend/node_modules/strtok3/lib/stream/index.js generated vendored Normal file
View File

@@ -0,0 +1,5 @@
export { AbortError, EndOfStreamError } from './Errors.js';
export { StreamReader } from './StreamReader.js';
export { WebStreamByobReader } from './WebStreamByobReader.js';
export { WebStreamDefaultReader } from './WebStreamDefaultReader.js';
export { makeWebStreamReader } from './WebStreamReaderFactory.js';