Compare commits

...

25 Commits

Author SHA1 Message Date
7a83ba855b email error msg 2025-06-20 19:09:57 +02:00
08eb28aae4 mix message 2025-06-20 19:05:07 +02:00
27b17f0ec3 email error 2025-06-20 19:03:52 +02:00
c9dabe2c09 verify email exists 2025-06-20 18:24:08 +02:00
b8b5d3c26c format 2025-06-20 18:09:26 +02:00
6ee0bc6f24 remove symlink 2025-06-20 18:08:57 +02:00
82e47f3a47 doc: update 2025-06-20 18:07:58 +02:00
59f8a6fdf9 exec script 2025-06-20 17:55:27 +02:00
04db25ec5a update script 2025-06-20 17:55:08 +02:00
7cdbb872b4 logout color 2025-06-20 17:51:35 +02:00
1e9740bf51 ignore temp xlsx 2025-06-20 17:49:01 +02:00
baba1b7ade color, text 2025-06-20 17:48:32 +02:00
55b9b80a4e add nvm 2025-06-20 17:31:24 +02:00
5c969eb51a oier test user 2025-06-20 17:29:06 +02:00
d466d05e79 container name 2025-06-10 01:21:12 +02:00
c63e5b6f16 compose data 2025-06-10 01:09:46 +02:00
f110ea1d9d docker ignore 2025-06-10 01:09:24 +02:00
68187fe5c6 docker stuff 2025-06-10 01:05:39 +02:00
627b999423 src fix 2025-06-10 01:05:27 +02:00
feeba4ff00 dev env 2025-06-10 01:04:57 +02:00
b9bf840c84 data ignore 2025-06-10 01:04:11 +02:00
2af3030840 example data 2025-06-10 00:44:18 +02:00
9d5147c060 Bigger buttons 2025-06-10 00:34:53 +02:00
56f6a45ccc centered grid 2025-06-10 00:28:28 +02:00
286ae5135d Component styles 2025-06-10 00:27:07 +02:00
15 changed files with 143 additions and 55 deletions

7
.dockerignore Normal file
View File

@@ -0,0 +1,7 @@
.DS_Store
node_modules
dist
data
example-data
.vscode
.astro

11
.env.development Normal file
View File

@@ -0,0 +1,11 @@
#XLSX
XLSX_AMOUNT_SOURCE=./example-data/saldos.xlsx
# Auth
AUTH_TRUST_HOST=false
AUTH_SECRET=fa428fc2e4c09d3b6dd914cfef0ddd1e
# Keycloak Configuration
KEYCLOAK_CLIENT_ID=karkarcar
KEYCLOAK_CLIENT_SECRET=fdI1OtyX0YNNUMqfcsbSMFTv9WfzQQwy
KEYCLOAK_ISSUER=http://localhost:8180/realms/master

2
.gitignore vendored
View File

@@ -22,3 +22,5 @@ pnpm-debug.log*
# jetbrains setting folder # jetbrains setting folder
.idea/ .idea/
data/
example-data/.~lock.saldos.xlsx#

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
22

26
Dockerfile Normal file
View File

@@ -0,0 +1,26 @@
FROM node:lts AS base
WORKDIR /app
# By copying only the package.json and package-lock.json here, we ensure that the following `-deps` steps are independent of the source code.
# Therefore, the `-deps` steps will be skipped if only the source code changes.
COPY package.json package-lock.json ./
FROM base AS prod-deps
RUN npm install --omit=dev
FROM base AS build-deps
RUN npm install
FROM build-deps AS build
COPY . .
RUN npm run build
FROM base AS runtime
COPY --from=prod-deps /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
ENV HOST=0.0.0.0
ENV PORT=4321
EXPOSE 4321
CMD node ./dist/server/entry.mjs

16
docker-compose.yml Normal file
View File

@@ -0,0 +1,16 @@
version: '3.8'
services:
app:
container_name: karkarcar_saldo_app
build:
context: .
dockerfile: Dockerfile
ports:
- "4321:4321"
environment:
- HOST=0.0.0.0
- PORT=4321
restart: unless-stopped
volumes:
- ./data:/data

View File

@@ -1 +0,0 @@
,oier,XPS24,09.06.2025 18:50,file:///home/oier/.config/libreoffice/4;

Binary file not shown.

14
scp.md Normal file
View File

@@ -0,0 +1,14 @@
# SCP karkarcar.oier.ovh
## `~/.ssh/config`
```
Host karkarcar
Hostname 149.202.89.131
User ubuntu
IdentityFile ~/.ssh/id_rsa
```
- `scp RUTA.XLSX karkarcar:~/pmc/karkarcar-astro/data/saldos.xlsx`
- `ssh -t karkarcar 'cd ~/pmc/karkarcar-astro/; ./update.sh'`

View File

@@ -37,7 +37,7 @@ export async function getUser(req: Request, options = authConfig): Promise<KarKa
export interface UserAmount { export interface UserAmount {
amount?: String | null; amount?: number | null;
} }
async function getUserAmount(email: String | null | undefined): Promise<UserAmount | null> { async function getUserAmount(email: String | null | undefined): Promise<UserAmount | null> {
@@ -56,25 +56,8 @@ async function getUserAmount(email: String | null | undefined): Promise<UserAmou
}) })
} }
let userData = data.filter(data => data.Email == email) let userData = data.filter(data => data.Email == email)
if(userData[0] == undefined)
return{amount:0}
return {amount:userData[0]['Saldo Actual']}; return {amount:userData[0]['Saldo Actual'] ? userData[0]['Saldo Actual'] : 0};
}
function getUserData(){
const file = readFile(env.XLSX_AMOUNT_SOURCE);
let data = []
const sheets = file.SheetNames
for(let i = 0; i < sheets.length; i++)
{
const temp = utils.sheet_to_json(
file.Sheets[file.SheetNames[i]])
temp.forEach((res) => {
data.push(res)
})
}
let userData = data.filter(data => data.Email == email)
return {amount:userData[0]['Saldo Actual']};
} }

View File

@@ -1,19 +1,14 @@
--- ---
import type { KarKarCarSession } from "../api/index.ts"
import { getUser } from "../api/index" import { getUser } from "../api/index"
import type FullAuthConfig from 'auth-astro'
import config from 'auth:config' import config from 'auth:config'
import authConfig from 'auth:config'
interface Props { const { class: className, ...rest } = Astro.props;
authConfig?: typeof config
}
const { authConfig = config } = Astro.props as Props
let session = await getUser(Astro.request, authConfig) let session = await getUser(Astro.request, authConfig)
--- ---
<div> <div class={className}>
<Fragment set:html={Astro.slots.render('default', [session])} /> <Fragment set:html={Astro.slots.render('default', [session])} />
</div> </div>

View File

@@ -0,0 +1,24 @@
---
import type { KarKarCarSession } from "../api/index.ts";
interface Props {
session: KarKarCarSession | null;
}
const { session } = Astro.props;
---
{session && session.userData && session.userData.amount? (
<div class="text-gray-700">
<h2 class="m-0 mb-4 text-slate-800">{session.user?.email}</h2>
<div class="bg-white p-4 rounded shadow-sm">
<p>Saldo: <strong>{session.userData.amount}€</strong></p>
</div>
</div>
) : (
<div>
{session && session.userData &&<p>E-Mail okerra. E-Mail incorrecto</p>}
{session && session.userData && <em>{session.user?.email}</em>}
{session && session.userData && <p><strong>Bidali e-mail bat/Envia un correo a: <a href="mailto:j0s3b4@protomakers.club">j0s3b4@protomakers.club</a></strong></p>}
</div>
)}

View File

@@ -5,11 +5,7 @@ interface Props {
const { title = "KarkarCar" } = Astro.props; const { title = "KarkarCar" } = Astro.props;
import { Image } from 'astro:assets'; import '../styles/global.css'
import logo from './src/images/logo-urdina.png';
import './src/styles/global.css'
--- ---
<!DOCTYPE html> <!DOCTYPE html>
@@ -20,7 +16,10 @@ import './src/styles/global.css'
<title>{title}</title> <title>{title}</title>
</head> </head>
<body> <body>
<Image src={logo} alt="KarKarCar" /> <div class="min-h-screen grid place-items-center">
<slot /> <div class="grid gap-6 text-center">
<slot />
</div>
</div>
</body> </body>
</html> </html>

View File

@@ -5,29 +5,30 @@ import { SignIn, SignOut } from 'auth-astro/components';
import KarKarCarAuth from "../components/KarKarCarAuth.astro" import KarKarCarAuth from "../components/KarKarCarAuth.astro"
// 1. Import any dependencies (Full support for JavaScript/TypeScript) // 1. Import any dependencies (Full support for JavaScript/TypeScript)
import type { KarKarCarSession } from "../api/index.ts" import { getUser, type KarKarCarSession } from "../api/index"
import UserInfo from "../components/UserInfo.astro"
import config from 'auth:config'
import { Image } from 'astro:assets';
import logo from '../images/logo-urdina.png';
const session = await getUser(Astro.request, config);
--- ---
<Layout> <Layout>
<div class="flex justify-center">
<Image src={logo} alt="KarKarCar" class="max-w-xs" />
</div>
<UserInfo session={session} />
<KarKarCarAuth> <KarKarCarAuth>
{(session: KarKarCarSession) => ( {(session: KarKarCarSession) => (
<>
<> {session ?
{session ? <SignOut class="px-8 py-4 text-white rounded-lg hover:bg-red-700 transition-colors duration-200 font-medium text-xl" style="background-color: #dc3545;">Irten/Salir</SignOut>
<SignOut>Logout</SignOut> :
: <SignIn provider="keycloak" class="px-8 py-4 text-white rounded-lg hover:bg-blue-700 transition-colors duration-200 font-medium text-xl" style="background-color: #005f7d;">Sartu/Entrar</SignIn>
<SignIn provider="keycloak">Login</SignIn> }
} </>
<p>
{session ? `Logged in as ${session.user?.name}` : 'Not logged in'}
{session ? `Amount ${session.userData.amount}` : ''}
</p>
</>
)} )}
</KarKarCarAuth> </KarKarCarAuth>
</Layout> </Layout>

10
update.sh Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/bash
# Update the project
git pull
# Build the project
docker compose build
# Restart the project
docker compose up -d