From e6d92f27b3be810eec95f28295711a4e30fe0aa2 Mon Sep 17 00:00:00 2001
From: root
Date: Thu, 18 Jun 2026 17:00:00 +0200
Subject: [PATCH] Migrate JavaScript to TypeScript with full type safety
- Rename all .js/.jsx files to .ts/.tsx across resources/js and theme dirs
- Add TypeScript 6.0 with strict mode, tsconfig.json
- Add type definitions for Inertia page props, Alpine.js, Turbolinks
- Update vite.config.js entries to .ts/.tsx extensions
- Update all Blade @vite() calls to match new .ts/.tsx entry points
- Add TypeScript ESLint config (replacing unused Vue plugin)
- Add @types/react, @types/react-dom, @types/lodash
- Add typecheck script and integrate into check pipeline
- Full tsc --noEmit, ESLint, and production build pass cleanly
---
eslint.config.js | 25 ++-
package.json | 19 +-
public/build/manifest.json | 106 +++++++--
resources/js/bootstrap.js | 34 ---
resources/js/bootstrap.ts | 6 +
resources/js/{global.js => global.ts} | 0
resources/js/pages/Home.jsx | 31 ---
resources/js/pages/Home.tsx | 43 ++++
resources/js/pages/Index.jsx | 119 ----------
resources/js/pages/Index.tsx | 206 ++++++++++++++++++
resources/js/ssr.jsx | 12 -
resources/js/ssr.tsx | 16 ++
resources/js/types.d.ts | 31 +++
resources/themes/atom/js/app.js | 25 ---
resources/themes/atom/js/app.ts | 18 ++
resources/themes/atom/js/bootstrap.js | 34 ---
resources/themes/atom/js/bootstrap.ts | 7 +
.../atom/js/components/ArticleReactions.js | 131 -----------
.../atom/js/components/ArticleReactions.ts | 147 +++++++++++++
.../{AtomSliders.js => AtomSliders.ts} | 7 +-
.../{ThemeSwitcher.js => ThemeSwitcher.ts} | 15 +-
.../themes/atom/views/client/nitro.blade.php | 2 +-
.../themes/atom/views/layouts/app.blade.php | 2 +-
.../themes/atom/views/layouts/guest.blade.php | 2 +-
.../themes/atom/views/maintenance.blade.php | 2 +-
resources/themes/atom/vite.config.js | 8 +-
resources/themes/dusk/js/app.js | 40 ----
resources/themes/dusk/js/app.ts | 36 +++
resources/themes/dusk/js/bootstrap.js | 31 ---
resources/themes/dusk/js/bootstrap.ts | 4 +
.../dusk/js/components/ArticleReactions.js | 131 -----------
.../dusk/js/components/ArticleReactions.ts | 147 +++++++++++++
.../themes/dusk/views/client/nitro.blade.php | 2 +-
.../themes/dusk/views/layouts/app.blade.php | 2 +-
.../themes/dusk/views/maintenance.blade.php | 2 +-
resources/themes/dusk/vite.config.js | 8 +-
resources/views/app.blade.php | 2 +-
.../views/layouts/installation.blade.php | 2 +-
tsconfig.json | 30 +++
vite.config.js | 4 +-
yarn.lock | 177 ++++++++++++---
41 files changed, 986 insertions(+), 680 deletions(-)
delete mode 100755 resources/js/bootstrap.js
create mode 100755 resources/js/bootstrap.ts
rename resources/js/{global.js => global.ts} (100%)
delete mode 100755 resources/js/pages/Home.jsx
create mode 100755 resources/js/pages/Home.tsx
delete mode 100755 resources/js/pages/Index.jsx
create mode 100755 resources/js/pages/Index.tsx
delete mode 100755 resources/js/ssr.jsx
create mode 100755 resources/js/ssr.tsx
create mode 100644 resources/js/types.d.ts
delete mode 100755 resources/themes/atom/js/app.js
create mode 100755 resources/themes/atom/js/app.ts
delete mode 100755 resources/themes/atom/js/bootstrap.js
create mode 100755 resources/themes/atom/js/bootstrap.ts
delete mode 100755 resources/themes/atom/js/components/ArticleReactions.js
create mode 100755 resources/themes/atom/js/components/ArticleReactions.ts
rename resources/themes/atom/js/components/{AtomSliders.js => AtomSliders.ts} (83%)
rename resources/themes/atom/js/components/{ThemeSwitcher.js => ThemeSwitcher.ts} (71%)
delete mode 100755 resources/themes/dusk/js/app.js
create mode 100755 resources/themes/dusk/js/app.ts
delete mode 100755 resources/themes/dusk/js/bootstrap.js
create mode 100755 resources/themes/dusk/js/bootstrap.ts
delete mode 100755 resources/themes/dusk/js/components/ArticleReactions.js
create mode 100755 resources/themes/dusk/js/components/ArticleReactions.ts
create mode 100644 tsconfig.json
diff --git a/eslint.config.js b/eslint.config.js
index 5f2f610..a0ec258 100755
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -1,5 +1,6 @@
import globals from "globals";
-import pluginVue from "eslint-plugin-vue";
+import tseslint from "@typescript-eslint/eslint-plugin";
+import tsParser from "@typescript-eslint/parser";
export default [
{
@@ -11,22 +12,32 @@ export default [
"build/**",
],
},
- ...pluginVue.configs["flat/essential"],
{
+ files: ["**/*.{ts,tsx}"],
languageOptions: {
+ parser: tsParser,
+ parserOptions: {
+ ecmaVersion: "latest",
+ sourceType: "module",
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
globals: {
...globals.browser,
...globals.node,
- Alpine: "readonly",
- $: "readonly",
- jQuery: "readonly",
},
},
+ plugins: {
+ "@typescript-eslint": tseslint,
+ },
rules: {
"no-console": "warn",
"no-debugger": "warn",
- "vue/multi-word-component-names": "off",
- "vue/no-v-html": "off",
+ "@typescript-eslint/no-unused-vars": [
+ "warn",
+ { argsIgnorePattern: "^_" },
+ ],
},
},
];
diff --git a/package.json b/package.json
index 88e28ef..7634b12 100755
--- a/package.json
+++ b/package.json
@@ -8,16 +8,17 @@
"build:atom": "vite build --config resources/themes/atom/vite.config.js && php artisan optimize:clear && php artisan optimize && chown -R www-data:www-data public/build",
"build:dusk": "vite build --config resources/themes/dusk/vite.config.js && php artisan optimize:clear && php artisan optimize && chown -R www-data:www-data public/build",
"build:all": "vite build --config resources/themes/atom/vite.config.js && vite build --config resources/themes/dusk/vite.config.js && php artisan optimize:clear && php artisan optimize && chown -R www-data:www-data public/build",
+ "typecheck": "tsc --noEmit",
"preview": "vite preview",
- "format": "prettier \"resources/**/*.{js,ts,vue,blade}\" --ignore-unknown --write",
- "format:check": "prettier \"resources/**/*.{js,ts,vue,blade.php}\" --check",
- "lint": "eslint resources/js/",
- "lint:fix": "eslint resources/js/ --fix",
+ "format": "prettier \"resources/**/*.{js,ts,tsx,vue,blade}\" --ignore-unknown --write",
+ "format:check": "prettier \"resources/**/*.{js,ts,tsx,vue,blade.php}\" --check",
+ "lint": "eslint \"resources/js/\" --ext .ts,.tsx",
+ "lint:fix": "eslint \"resources/js/\" --ext .ts,.tsx --fix",
"lint:css": "stylelint \"resources/**/*.css\"",
"lint:css:fix": "stylelint \"resources/**/*.css\" --fix",
"lint:all": "yarn lint && yarn lint:css",
"lint:fix:all": "yarn lint:fix && yarn lint:fix:css",
- "check": "yarn lint:all && yarn format:check",
+ "check": "yarn typecheck && yarn lint:all && yarn format:check",
"check:php": "php -l app/ && php -l routes/ && php -l database/ && php -l resources/",
"check:security": "composer audit && npm audit",
"check:deps": "npm outdated --long --json || true",
@@ -33,12 +34,17 @@
"@tailwindcss/forms": "0.5.11",
"@tailwindcss/postcss": "4.3.0",
"@tailwindcss/typography": "0.5.19",
+ "@types/lodash": "^4.17.24",
+ "@types/react": "^19.2.17",
+ "@types/react-dom": "^19.2.3",
+ "@typescript-eslint/eslint-plugin": "^8.61.1",
+ "@typescript-eslint/parser": "^8.61.1",
"alpinejs": "3.15.12",
"autoprefixer": "10.5.0",
"axios": "^1.17.0",
"esbuild": "^0.28.0",
"eslint": "^10.4.1",
- "eslint-plugin-vue": "10.9.2",
+ "globals": "^17.6.0",
"laravel-vite-plugin": "^3.1.0",
"lodash": "^4.18.1",
"postcss": "8.5.15",
@@ -49,6 +55,7 @@
"stylelint-config-standard": "^40.0.0",
"tailwindcss": "4.3.0",
"turbolinks": "5.2.0",
+ "typescript": "^6.0.3",
"vite": "^8.0.16"
},
"dependencies": {
diff --git a/public/build/manifest.json b/public/build/manifest.json
index f7d8067..7bc56e7 100644
--- a/public/build/manifest.json
+++ b/public/build/manifest.json
@@ -1,15 +1,26 @@
{
- "_axios-Bb9VWCvi.js": {
- "file": "assets/axios-Bb9VWCvi.js",
+ "_axios-BEkq_c61.js": {
+ "file": "assets/axios-BEkq_c61.js",
"name": "axios",
"imports": [
- "_chunk-QTnfLwEv.js"
+ "_chunk-b3L32Ng1.js"
]
},
- "_chunk-QTnfLwEv.js": {
- "file": "assets/chunk-QTnfLwEv.js",
+ "_chunk-b3L32Ng1.js": {
+ "file": "assets/chunk-b3L32Ng1.js",
"name": "chunk"
},
+ "_swiper-Cjlszzo3.js": {
+ "file": "assets/swiper-Cjlszzo3.js",
+ "name": "swiper",
+ "css": [
+ "assets/swiper-CrMA9oas.css"
+ ]
+ },
+ "_swiper-CrMA9oas.css": {
+ "file": "assets/swiper-CrMA9oas.css",
+ "src": "_swiper-CrMA9oas.css"
+ },
"public/assets/images/background-dark.jpg": {
"file": "assets/background-dark-BfkMu3-0.jpg",
"src": "public/assets/images/background-dark.jpg"
@@ -18,6 +29,18 @@
"file": "assets/background-light-CP7oKwVT.jpg",
"src": "public/assets/images/background-light.jpg"
},
+ "public/assets/images/dusk/background_image.png": {
+ "file": "assets/background_image-BH7pVpv1.png",
+ "src": "public/assets/images/dusk/background_image.png"
+ },
+ "public/assets/images/dusk/leaderboard_circle_image.png": {
+ "file": "assets/leaderboard_circle_image-BYkDVX69.png",
+ "src": "public/assets/images/dusk/leaderboard_circle_image.png"
+ },
+ "public/assets/images/dusk/store_icon.png": {
+ "file": "assets/store_icon-B52tsSKO.png",
+ "src": "public/assets/images/dusk/store_icon.png"
+ },
"public/assets/images/icons/article.gif": {
"file": "assets/article-CYhGsSKA.gif",
"src": "public/assets/images/icons/article.gif"
@@ -111,7 +134,7 @@
"src": "public/assets/images/profile/profile-bg.png"
},
"resources/css/global.css": {
- "file": "assets/global-DmKtm1TC.css",
+ "file": "assets/global-CwMfkl9f.css",
"name": "global",
"names": [
"global.css"
@@ -146,27 +169,27 @@
"assets/community-Do_t1zw9.png"
]
},
- "resources/js/global.js": {
- "file": "assets/global-r22-sRCc.js",
+ "resources/js/global.ts": {
+ "file": "assets/global-B6tm4RcQ.js",
"name": "global",
- "src": "resources/js/global.js",
+ "src": "resources/js/global.ts",
"isEntry": true,
"imports": [
- "_chunk-QTnfLwEv.js",
- "_axios-Bb9VWCvi.js"
+ "_chunk-b3L32Ng1.js",
+ "_axios-BEkq_c61.js"
]
},
- "resources/js/ssr.jsx": {
- "file": "assets/ssr-DdmZbD73.js",
+ "resources/js/ssr.tsx": {
+ "file": "assets/ssr-GVDc-G73.js",
"name": "ssr",
- "src": "resources/js/ssr.jsx",
+ "src": "resources/js/ssr.tsx",
"isEntry": true,
"imports": [
- "_chunk-QTnfLwEv.js"
+ "_chunk-b3L32Ng1.js"
]
},
"resources/themes/atom/css/app.css": {
- "file": "assets/app-DtTGSxkD.css",
+ "file": "assets/app-BPKvU7LK.css",
"name": "app",
"names": [
"app.css"
@@ -201,17 +224,56 @@
"assets/community-Do_t1zw9.png"
]
},
- "resources/themes/atom/js/app.js": {
- "file": "assets/app-CAkt-7PZ.js",
+ "resources/themes/atom/js/app.ts": {
+ "file": "assets/app-evCrhLY1.js",
"name": "app",
- "src": "resources/themes/atom/js/app.js",
+ "src": "resources/themes/atom/js/app.ts",
"isEntry": true,
"imports": [
- "_chunk-QTnfLwEv.js",
- "_axios-Bb9VWCvi.js"
+ "_chunk-b3L32Ng1.js",
+ "_swiper-Cjlszzo3.js",
+ "_axios-BEkq_c61.js"
+ ]
+ },
+ "resources/themes/dusk/css/app.css": {
+ "file": "assets/app-CHSILL1f.css",
+ "name": "app",
+ "names": [
+ "app.css"
+ ],
+ "src": "resources/themes/dusk/css/app.css",
+ "isEntry": true,
+ "assets": [
+ "assets/background_image-BH7pVpv1.png",
+ "assets/feeds-BtHcJdHX.png",
+ "assets/chat-r5H1PnTg.png",
+ "assets/article-CYhGsSKA.gif",
+ "assets/lighthouse-BON6qnQ0.png",
+ "assets/store_icon-B52tsSKO.png",
+ "assets/catalog-D-956oDx.png",
+ "assets/inventory-BlHYLNGT.png",
+ "assets/due-chat-CeO4yxLu.png",
+ "assets/friends-BxpcKlvz.png",
+ "assets/credits-Dpg5Nmby.png",
+ "assets/duckets-CaGJI1Oy.png",
+ "assets/diamonds-BtfqKoQu.png",
+ "assets/trophy-gold-bbKmpkii.png",
+ "assets/trophy-silver-bGfHJkQ_.png",
+ "assets/trophy-bronze-CgV5j1MU.png",
+ "assets/leaderboard_circle_image-BYkDVX69.png"
+ ]
+ },
+ "resources/themes/dusk/js/app.ts": {
+ "file": "assets/app-DKy1JARZ.js",
+ "name": "app",
+ "src": "resources/themes/dusk/js/app.ts",
+ "isEntry": true,
+ "imports": [
+ "_swiper-Cjlszzo3.js",
+ "_axios-BEkq_c61.js"
],
"css": [
- "assets/app-CeYfhhVD.css"
+ "assets/app-DU8Y3NnC.css"
]
}
}
\ No newline at end of file
diff --git a/resources/js/bootstrap.js b/resources/js/bootstrap.js
deleted file mode 100755
index 34478d4..0000000
--- a/resources/js/bootstrap.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import _ from "lodash";
-window._ = _;
-
-/**
- * We'll load the axios HTTP library which allows us to easily issue requests
- * to our Laravel back-end. This library automatically handles sending the
- * CSRF token as a header based on the value of the "XSRF" token cookie.
- */
-
-import axios from "axios";
-window.axios = axios;
-
-window.axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
-
-/**
- * Echo exposes an expressive API for subscribing to channels and listening
- * for events that are broadcast by Laravel. Echo and event broadcasting
- * allows your team to easily build robust real-time web applications.
- */
-
-// import Echo from 'laravel-echo';
-
-// import Pusher from 'pusher-js';
-// window.Pusher = Pusher;
-
-// window.Echo = new Echo({
-// broadcaster: 'pusher',
-// key: import.meta.env.VITE_PUSHER_APP_KEY,
-// wsHost: import.meta.env.VITE_PUSHER_HOST ?? `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
-// wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
-// wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
-// forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
-// enabledTransports: ['ws', 'wss'],
-// });
diff --git a/resources/js/bootstrap.ts b/resources/js/bootstrap.ts
new file mode 100755
index 0000000..11434e8
--- /dev/null
+++ b/resources/js/bootstrap.ts
@@ -0,0 +1,6 @@
+import _ from "lodash";
+import axios from "axios";
+
+window._ = _;
+window.axios = axios;
+window.axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
diff --git a/resources/js/global.js b/resources/js/global.ts
similarity index 100%
rename from resources/js/global.js
rename to resources/js/global.ts
diff --git a/resources/js/pages/Home.jsx b/resources/js/pages/Home.jsx
deleted file mode 100755
index e0bf985..0000000
--- a/resources/js/pages/Home.jsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import { Head } from '@inertiajs/react'
-
-export default function Home({ auth, hotelName }) {
- return (
- <>
-
-
-
-
- Welkom bij {hotelName}
-
-
- Dit is een Inertia.js pagina — zelfde layout, zelfde Tailwind, zelfde stijlen.
-
-
-
-
- >
- )
-}
diff --git a/resources/js/pages/Home.tsx b/resources/js/pages/Home.tsx
new file mode 100755
index 0000000..34ce8c2
--- /dev/null
+++ b/resources/js/pages/Home.tsx
@@ -0,0 +1,43 @@
+import { Head } from "@inertiajs/react";
+
+interface HomeProps {
+ auth: Record;
+ hotelName: string;
+}
+
+export default function Home({ hotelName }: HomeProps) {
+ return (
+ <>
+
+
+
+
+ Welkom bij {hotelName}
+
+
+ Dit is een Inertia.js pagina — zelfde layout, zelfde Tailwind,
+ zelfde stijlen.
+
+
+
+
+ >
+ );
+}
diff --git a/resources/js/pages/Index.jsx b/resources/js/pages/Index.jsx
deleted file mode 100755
index 4d3a3fa..0000000
--- a/resources/js/pages/Index.jsx
+++ /dev/null
@@ -1,119 +0,0 @@
-import { Head, usePage } from '@inertiajs/react'
-
-export default function Index({ articles, photos }) {
- const { avatarImager } = usePage().props
-
- return (
- <>
-