first commit
This commit is contained in:
10
.gemini/settings.json
Normal file
10
.gemini/settings.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"chrome-devtools": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"chrome-devtools-mcp@latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
# Keep environment variables out of version control
|
||||
.env
|
||||
|
||||
/generated/prisma
|
||||
4
.prettierrc
Normal file
4
.prettierrc
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
||||
55
README.md
Normal file
55
README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# EventQR (NestJS + React)
|
||||
|
||||
A unified EventQR project with a NestJS backend and React frontend.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js
|
||||
- PostgreSQL Database
|
||||
|
||||
## Setup
|
||||
|
||||
1. **Configure Database:**
|
||||
Update `.env` with your PostgreSQL connection string.
|
||||
```env
|
||||
DATABASE_URL="postgresql://user:password@localhost:5432/eventqr"
|
||||
JWT_SECRET="your-secret"
|
||||
PASSWORD="your-login-password"
|
||||
```
|
||||
|
||||
2. **Install Dependencies:**
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
3. **Setup Database:**
|
||||
```bash
|
||||
npx prisma migrate dev --name init
|
||||
```
|
||||
|
||||
4. **Build Frontend:**
|
||||
```bash
|
||||
npm run build:client
|
||||
```
|
||||
|
||||
5. **Start Server:**
|
||||
```bash
|
||||
npm run start:dev
|
||||
```
|
||||
|
||||
The application will be available at `http://localhost:3000`.
|
||||
API endpoints are at `http://localhost:3000/api`.
|
||||
|
||||
## Features
|
||||
|
||||
- **Auth:** JWT-based authentication with a simple password check (configured in `.env`).
|
||||
- **Events:** Create and list events.
|
||||
- **Tickets:** Generate tickets (Types: "Klassenbester", "1er Schüler", "Partyborner"). Scan and validate tickets.
|
||||
- **Frontend:** React app served statically by NestJS.
|
||||
|
||||
## Development
|
||||
|
||||
- Backend: `src/`
|
||||
- Frontend: `client/`
|
||||
|
||||
To work on the frontend, you can run `cd client && npm run dev` for hot-reloading, but you need to ensure it can proxy to the backend (configured in `vite.config.ts` to proxy `/api` to `http://localhost:3000`).
|
||||
1
client/dist/assets/index-CB33grvy.css
vendored
Normal file
1
client/dist/assets/index-CB33grvy.css
vendored
Normal file
File diff suppressed because one or more lines are too long
30
client/dist/assets/index-DOfJxXvf.js
vendored
Normal file
30
client/dist/assets/index-DOfJxXvf.js
vendored
Normal file
File diff suppressed because one or more lines are too long
14
client/dist/index.html
vendored
Normal file
14
client/dist/index.html
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>event-qr-tool</title>
|
||||
<script type="module" crossorigin src="/assets/index-DOfJxXvf.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CB33grvy.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
13
client/index.html
Normal file
13
client/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>event-qr-tool</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
4245
client/package-lock.json
generated
Normal file
4245
client/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
40
client/package.json
Normal file
40
client/package.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "event-qr-client",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc -b && vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/qrcode.react": "^1.0.5",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"html5-qrcode": "^2.3.8",
|
||||
"lucide-react": "^0.555.0",
|
||||
"qrcode.react": "^4.2.0",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0",
|
||||
"react-router-dom": "^7.9.6",
|
||||
"uuid": "^13.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.1",
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/react": "^19.2.5",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.1",
|
||||
"autoprefixer": "^10.4.22",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.24",
|
||||
"globals": "^16.5.0",
|
||||
"postcss": "^8.5.6",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"typescript": "~5.9.3",
|
||||
"typescript-eslint": "^8.46.4",
|
||||
"vite": "^7.2.4"
|
||||
}
|
||||
}
|
||||
6
client/postcss.config.js
Normal file
6
client/postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
30
client/src/App.tsx
Normal file
30
client/src/App.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
|
||||
import { Layout } from './components/Layout';
|
||||
import { Home } from './pages/Home';
|
||||
import { Generate } from './pages/Generate';
|
||||
import { Scan } from './pages/Scan';
|
||||
import { Login } from './pages/Login';
|
||||
import { AuthProvider } from './context/AuthContext';
|
||||
import { ProtectedRoute } from './components/ProtectedRoute';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<AuthProvider>
|
||||
<Router>
|
||||
<Routes>
|
||||
<Route path="/login" element={<Login />} />
|
||||
|
||||
<Route element={<ProtectedRoute />}>
|
||||
<Route element={<Layout />}>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/generate" element={<Generate />} />
|
||||
<Route path="/scan" element={<Scan />} />
|
||||
</Route>
|
||||
</Route>
|
||||
</Routes>
|
||||
</Router>
|
||||
</AuthProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
72
client/src/components/Layout.tsx
Normal file
72
client/src/components/Layout.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import React from 'react';
|
||||
import { Link, useLocation, useNavigate, Outlet } from 'react-router-dom';
|
||||
import { QrCode, Scan, Calendar, Mail, LogOut } from 'lucide-react';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
|
||||
export const Layout: React.FC = () => {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const { logout } = useAuth();
|
||||
|
||||
const isActive = (path: string) => location.pathname === path;
|
||||
|
||||
const handleLogout = () => {
|
||||
logout();
|
||||
navigate('/login');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<nav className="glass-panel sticky top-0 z-50 border-x-0 border-t-0 rounded-none">
|
||||
<div className="container py-4 flex justify-between items-center">
|
||||
<Link to="/" className="text-2xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-indigo-400 to-purple-400 flex items-center gap-2">
|
||||
<QrCode className="text-indigo-400" />
|
||||
EventQR
|
||||
</Link>
|
||||
|
||||
<div className="flex gap-6 items-center">
|
||||
<Link
|
||||
to="/"
|
||||
className={`flex items-center gap-2 hover:text-indigo-400 transition-colors ${isActive('/') ? 'text-indigo-400' : 'text-slate-400'}`}
|
||||
>
|
||||
<Calendar size={20} />
|
||||
<span className="hidden sm:inline">Events</span>
|
||||
</Link>
|
||||
<Link
|
||||
to="/generate"
|
||||
className={`flex items-center gap-2 hover:text-indigo-400 transition-colors ${isActive('/generate') ? 'text-indigo-400' : 'text-slate-400'}`}
|
||||
>
|
||||
<Mail size={20} />
|
||||
<span className="hidden sm:inline">Generate</span>
|
||||
</Link>
|
||||
<Link
|
||||
to="/scan"
|
||||
className={`flex items-center gap-2 hover:text-indigo-400 transition-colors ${isActive('/scan') ? 'text-indigo-400' : 'text-slate-400'}`}
|
||||
>
|
||||
<Scan size={20} />
|
||||
<span className="hidden sm:inline">Scan</span>
|
||||
</Link>
|
||||
|
||||
<div className="w-px h-6 bg-slate-700 mx-2"></div>
|
||||
|
||||
<button
|
||||
onClick={handleLogout}
|
||||
className="flex items-center gap-2 text-slate-400 hover:text-red-400 transition-colors"
|
||||
title="Logout"
|
||||
>
|
||||
<LogOut size={20} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main className="flex-1 container py-8 page-transition">
|
||||
<Outlet />
|
||||
</main>
|
||||
|
||||
<footer className="py-6 text-center text-slate-600 text-sm">
|
||||
<p>© 2024 EventQR Tool. Built for seamless event management.</p>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
13
client/src/components/ProtectedRoute.tsx
Normal file
13
client/src/components/ProtectedRoute.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import { Navigate, Outlet } from 'react-router-dom';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
|
||||
export const ProtectedRoute: React.FC = () => {
|
||||
const { isAuthenticated } = useAuth();
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return <Navigate to="/login" replace />;
|
||||
}
|
||||
|
||||
return <Outlet />;
|
||||
};
|
||||
69
client/src/context/AuthContext.tsx
Normal file
69
client/src/context/AuthContext.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import React, { createContext, useContext, useState, useEffect } from 'react';
|
||||
|
||||
interface AuthContextType {
|
||||
isAuthenticated: boolean;
|
||||
login: (password: string) => Promise<boolean>;
|
||||
logout: () => void;
|
||||
}
|
||||
|
||||
const AuthContext = createContext<AuthContextType | null>(null);
|
||||
|
||||
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const token = sessionStorage.getItem('eventqr_token');
|
||||
if (token) {
|
||||
setIsAuthenticated(true);
|
||||
}
|
||||
setIsLoading(false);
|
||||
}, []);
|
||||
|
||||
const login = async (password: string) => {
|
||||
try {
|
||||
const response = await fetch('/api/login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ password }),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
if (data.accessToken) {
|
||||
sessionStorage.setItem('eventqr_token', data.accessToken);
|
||||
setIsAuthenticated(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error('Login failed:', error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
sessionStorage.removeItem('eventqr_token');
|
||||
setIsAuthenticated(false);
|
||||
fetch('/api/logout', { method: 'POST' });
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ isAuthenticated, login, logout }}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useAuth = () => {
|
||||
const context = useContext(AuthContext);
|
||||
if (!context) {
|
||||
throw new Error('useAuth must be used within an AuthProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
177
client/src/index.css
Normal file
177
client/src/index.css
Normal file
@@ -0,0 +1,177 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
--bg-primary: #0f172a;
|
||||
--bg-secondary: #1e293b;
|
||||
--text-primary: #f8fafc;
|
||||
--text-secondary: #94a3b8;
|
||||
--accent-primary: #6366f1;
|
||||
--accent-secondary: #8b5cf6;
|
||||
--accent-gradient: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
||||
--success: #10b981;
|
||||
--error: #ef4444;
|
||||
--glass-bg: rgba(30, 41, 59, 0.7);
|
||||
--glass-border: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
||||
background-color: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
min-height: 100vh;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
#root {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.glass-panel {
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: 1rem;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--accent-gradient);
|
||||
color: white;
|
||||
padding: 0.75rem 1.5rem;
|
||||
border-radius: 0.5rem;
|
||||
font-weight: 600;
|
||||
transition: all 0.2s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
opacity: 0.9;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
padding: 0.75rem 1.5rem;
|
||||
border-radius: 0.5rem;
|
||||
font-weight: 600;
|
||||
border: 1px solid var(--glass-border);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: #334155;
|
||||
}
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
background: var(--bg-secondary);
|
||||
border: 1px solid var(--glass-border);
|
||||
color: var(--text-primary);
|
||||
padding: 0.75rem;
|
||||
border-radius: 0.5rem;
|
||||
width: 100%;
|
||||
font-size: 1rem;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
|
||||
input:focus,
|
||||
select:focus,
|
||||
textarea:focus {
|
||||
outline: none;
|
||||
border-color: var(--accent-primary);
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.page-transition {
|
||||
/* animation: fadeIn 0.3s ease-in-out; */
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Custom Scrollbar */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: var(--bg-primary);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--bg-secondary);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #475569;
|
||||
}
|
||||
|
||||
/* Scanner Overrides */
|
||||
#reader {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
#reader video {
|
||||
border-radius: 0.5rem;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
#reader__scan_region {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
#reader__dashboard_section_csr button {
|
||||
background: var(--accent-gradient) !important;
|
||||
color: white !important;
|
||||
border: none !important;
|
||||
padding: 0.5rem 1rem !important;
|
||||
border-radius: 0.5rem !important;
|
||||
font-weight: 600 !important;
|
||||
margin-top: 1rem !important;
|
||||
}
|
||||
|
||||
#reader__dashboard_section_swaplink {
|
||||
color: var(--accent-primary) !important;
|
||||
text-decoration: none !important;
|
||||
margin-top: 0.5rem !important;
|
||||
display: inline-block !important;
|
||||
}
|
||||
7
client/src/main.tsx
Normal file
7
client/src/main.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import './index.css'
|
||||
import App from './App.tsx'
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<App />
|
||||
)
|
||||
170
client/src/pages/Generate.tsx
Normal file
170
client/src/pages/Generate.tsx
Normal file
@@ -0,0 +1,170 @@
|
||||
import React, { useState } from 'react';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import { Save, RefreshCw, QrCode, Mail } from 'lucide-react';
|
||||
import { saveTicket, resendTicketEmail } from '../utils/storage';
|
||||
import type { Ticket } from '../types';
|
||||
|
||||
export const Generate: React.FC = () => {
|
||||
const [formData, setFormData] = useState({
|
||||
name: '',
|
||||
email: '',
|
||||
type: 'Klassenbester' as Ticket['ticketType']
|
||||
});
|
||||
const [generatedTicket, setGeneratedTicket] = useState<Ticket | null>(null);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
const [resendStatus, setResendStatus] = useState<'idle' | 'sending' | 'sent' | 'error'>('idle');
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setIsSaving(true);
|
||||
try {
|
||||
const ticketData = {
|
||||
eventId: 'default-event', // For now, single event
|
||||
attendeeName: formData.name,
|
||||
attendeeEmail: formData.email,
|
||||
ticketType: formData.type,
|
||||
};
|
||||
|
||||
const newTicket = await saveTicket(ticketData);
|
||||
setGeneratedTicket(newTicket);
|
||||
setResendStatus('idle'); // Reset resend status for new ticket
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
alert('Failed to generate ticket. Please try again.');
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleResendEmail = async () => {
|
||||
if (!generatedTicket) return;
|
||||
setResendStatus('sending');
|
||||
try {
|
||||
await resendTicketEmail(generatedTicket.id);
|
||||
setResendStatus('sent');
|
||||
setTimeout(() => setResendStatus('idle'), 3000); // Reset after 3 seconds
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
setResendStatus('error');
|
||||
}
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
setGeneratedTicket(null);
|
||||
setFormData({ name: '', email: '', type: 'Klassenbester' });
|
||||
setResendStatus('idle');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold mb-2">Generate Ticket</h1>
|
||||
<p className="text-slate-400">Create a new QR code ticket for an attendee.</p>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="glass-panel p-6 space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-2 text-slate-300">Attendee Name</label>
|
||||
<input
|
||||
required
|
||||
type="text"
|
||||
value={formData.name}
|
||||
onChange={e => setFormData({ ...formData, name: e.target.value })}
|
||||
placeholder="John Doe"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-2 text-slate-300">Email Address</label>
|
||||
<input
|
||||
required
|
||||
type="email"
|
||||
value={formData.email}
|
||||
onChange={e => setFormData({ ...formData, email: e.target.value })}
|
||||
placeholder="john@example.com"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-2 text-slate-300">Ticket Type</label>
|
||||
<select
|
||||
value={formData.type}
|
||||
onChange={e => setFormData({ ...formData, type: e.target.value as any })}
|
||||
>
|
||||
<option value="Klassenbester">Klassenbester</option>
|
||||
<option value="1er Schüler">1er Schüler</option>
|
||||
<option value="Partyborner">Partyborner</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button type="submit" className="btn-primary w-full justify-center mt-4" disabled={isSaving}>
|
||||
{isSaving ? 'Generating...' : (
|
||||
<>
|
||||
<Save size={18} />
|
||||
Generate Ticket
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
{generatedTicket ? (
|
||||
<div className="glass-panel p-8 text-center w-full max-w-sm animate-in fade-in zoom-in duration-300">
|
||||
<div className="bg-green-500/10 text-green-400 p-3 rounded-lg mb-6 text-sm font-medium">
|
||||
Ticket generated successfully!
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-4 rounded-lg inline-block mb-6">
|
||||
<QRCodeSVG
|
||||
value={JSON.stringify({ id: generatedTicket.id, type: generatedTicket.ticketType })}
|
||||
size={200}
|
||||
level="H"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h3 className="text-xl font-bold mb-1">{generatedTicket.attendeeName}</h3>
|
||||
<p className="text-slate-400 text-sm mb-6">{generatedTicket.ticketType} Ticket</p>
|
||||
|
||||
<div className="space-y-3">
|
||||
<button
|
||||
onClick={handleResendEmail}
|
||||
disabled={resendStatus === 'sending' || resendStatus === 'sent'}
|
||||
className={`w-full justify-center flex items-center gap-2 py-2 rounded-lg transition-colors font-medium ${
|
||||
resendStatus === 'sent'
|
||||
? 'bg-green-500/20 text-green-400 cursor-default'
|
||||
: 'bg-slate-700 hover:bg-slate-600 text-white'
|
||||
}`}
|
||||
>
|
||||
{resendStatus === 'sending' ? (
|
||||
'Sending...'
|
||||
) : resendStatus === 'sent' ? (
|
||||
'Email Sent!'
|
||||
) : (
|
||||
<>
|
||||
<Mail size={18} />
|
||||
Resend Email
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={reset}
|
||||
className="btn-secondary w-full justify-center"
|
||||
>
|
||||
<RefreshCw size={18} />
|
||||
Create Another
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center text-slate-500 p-12 border-2 border-dashed border-slate-700 rounded-xl">
|
||||
<QrCode size={48} className="mx-auto mb-4 opacity-50" />
|
||||
<p>Fill out the form to generate a ticket preview here.</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
142
client/src/pages/Home.tsx
Normal file
142
client/src/pages/Home.tsx
Normal file
@@ -0,0 +1,142 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Plus, Users, QrCode, Trash2 } from 'lucide-react';
|
||||
import { getTickets, deleteTicket } from '../utils/storage';
|
||||
import type { Ticket } from '../types';
|
||||
|
||||
export const Home: React.FC = () => {
|
||||
const [tickets, setTickets] = useState<Ticket[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const fetchTickets = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const fetchedTickets = await getTickets('default-event'); // For now, single event
|
||||
setTickets(fetchedTickets);
|
||||
} catch (err) {
|
||||
setError('Failed to load tickets.');
|
||||
console.error(err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
fetchTickets();
|
||||
}, []);
|
||||
|
||||
const handleDelete = async (id: string) => {
|
||||
if (window.confirm('Are you sure you want to delete this ticket?')) {
|
||||
try {
|
||||
await deleteTicket(id);
|
||||
setTickets(tickets.filter(t => t.id !== id));
|
||||
} catch (err) {
|
||||
alert('Failed to delete ticket.');
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<header className="flex justify-between items-end">
|
||||
<div>
|
||||
<h1 className="text-4xl font-bold mb-2">Dashboard</h1>
|
||||
<p className="text-slate-400">Manage your events and attendees</p>
|
||||
</div>
|
||||
<Link to="/generate" className="btn-primary">
|
||||
<Plus size={20} />
|
||||
New Ticket
|
||||
</Link>
|
||||
</header>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div className="glass-panel p-6">
|
||||
<div className="flex items-center gap-4 mb-4">
|
||||
<div className="p-3 bg-indigo-500/20 rounded-lg text-indigo-400">
|
||||
<Users size={24} />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-slate-400">Total Attendees</p>
|
||||
<p className="text-2xl font-bold">{tickets.length}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="glass-panel p-6">
|
||||
<div className="flex items-center gap-4 mb-4">
|
||||
<div className="p-3 bg-purple-500/20 rounded-lg text-purple-400">
|
||||
<QrCode size={24} />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-slate-400">Scanned Tickets</p>
|
||||
<p className="text-2xl font-bold">{tickets.filter(t => t.status === 'used').length}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="glass-panel p-6">
|
||||
<h2 className="text-xl font-bold mb-4">Recent Tickets</h2>
|
||||
{loading ? (
|
||||
<div className="text-center py-8 text-slate-500">
|
||||
Loading tickets...
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="text-center py-8 text-red-500">
|
||||
{error}
|
||||
</div>
|
||||
) : tickets.length === 0 ? (
|
||||
<div className="text-center py-8 text-slate-500">
|
||||
No tickets generated yet.
|
||||
</div>
|
||||
) : (
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-left border-collapse">
|
||||
<thead>
|
||||
<tr className="text-slate-400 border-b border-slate-700">
|
||||
<th className="p-4">Name</th>
|
||||
<th className="p-4">Email</th>
|
||||
<th className="p-4">Type</th>
|
||||
<th className="p-4">Status</th>
|
||||
<th className="p-4 text-right">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{tickets.slice().reverse().map(ticket => (
|
||||
<tr key={ticket.id} className="border-b border-slate-800 hover:bg-slate-800/50">
|
||||
<td className="p-4 font-medium">{ticket.attendeeName}</td>
|
||||
<td className="p-4 text-slate-400">{ticket.attendeeEmail}</td>
|
||||
<td className="p-4">
|
||||
<span className={`px-2 py-1 rounded-full text-xs ${ticket.ticketType === 'Partyborner' ? 'bg-amber-500/20 text-amber-400' : 'bg-blue-500/20 text-blue-400'
|
||||
}`}>
|
||||
{ticket.ticketType}
|
||||
</span>
|
||||
</td>
|
||||
<td className="p-4">
|
||||
<span className={`px-2 py-1 rounded-full text-xs ${ticket.status === 'valid' ? 'bg-green-500/20 text-green-400' : 'bg-slate-500/20 text-slate-400'
|
||||
}`}>
|
||||
{ticket.status}
|
||||
</span>
|
||||
</td>
|
||||
<td className="p-4 text-right">
|
||||
<button
|
||||
onClick={() => handleDelete(ticket.id)}
|
||||
className="text-slate-500 hover:text-red-400 transition-colors p-2"
|
||||
title="Delete Ticket"
|
||||
>
|
||||
<Trash2 size={18} />
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
65
client/src/pages/Login.tsx
Normal file
65
client/src/pages/Login.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
import { Lock } from 'lucide-react';
|
||||
|
||||
export const Login: React.FC = () => {
|
||||
const [password, setPassword] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const { login } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setError('');
|
||||
setIsSubmitting(true);
|
||||
try {
|
||||
const success = await login(password);
|
||||
if (success) {
|
||||
navigate('/');
|
||||
} else {
|
||||
setError('Invalid password');
|
||||
}
|
||||
} catch {
|
||||
setError('An error occurred. Please try again.');
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-slate-900 p-4">
|
||||
<div className="glass-panel p-8 w-full max-w-md">
|
||||
<div className="text-center mb-8">
|
||||
<div className="inline-block p-4 rounded-full bg-indigo-500/20 text-indigo-400 mb-4">
|
||||
<Lock size={32} />
|
||||
</div>
|
||||
<h1 className="text-2xl font-bold">EventQR Login</h1>
|
||||
<p className="text-slate-400">Please enter password to continue</p>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<div>
|
||||
<input
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
placeholder="Enter password"
|
||||
className="w-full bg-slate-800 border-slate-700 focus:border-indigo-500"
|
||||
autoFocus
|
||||
/>
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<p className="text-red-400 text-sm text-center">{error}</p>
|
||||
)}
|
||||
|
||||
<button type="submit" className="btn-primary w-full justify-center" disabled={isSubmitting}>
|
||||
{isSubmitting ? 'Logging in...' : 'Login'}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
128
client/src/pages/Scan.tsx
Normal file
128
client/src/pages/Scan.tsx
Normal file
@@ -0,0 +1,128 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Html5QrcodeScanner } from 'html5-qrcode';
|
||||
import { CheckCircle, XCircle, RefreshCw } from 'lucide-react';
|
||||
import { getTickets, updateTicketStatus } from '../utils/storage';
|
||||
import type { Ticket } from '../types';
|
||||
|
||||
export const Scan: React.FC = () => {
|
||||
const [scanResult, setScanResult] = useState<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
ticket?: Ticket;
|
||||
} | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Prevent scanner from initializing if we already have a result
|
||||
if (scanResult) return;
|
||||
|
||||
const scanner = new Html5QrcodeScanner(
|
||||
"reader",
|
||||
{ fps: 10, qrbox: { width: 250, height: 250 } },
|
||||
/* verbose= */ false
|
||||
);
|
||||
|
||||
scanner.render(
|
||||
async (decodedText) => {
|
||||
try {
|
||||
scanner.clear();
|
||||
const data = JSON.parse(decodedText);
|
||||
const tickets = await getTickets('default-event'); // Hardcoded event
|
||||
const ticket = tickets.find(t => t.id === data.id);
|
||||
|
||||
if (ticket) {
|
||||
if (ticket.status === 'valid') {
|
||||
const updatedTicket = await updateTicketStatus(ticket.id, 'used');
|
||||
setScanResult({
|
||||
success: true,
|
||||
message: 'Ticket Valid! Access Granted.',
|
||||
ticket: updatedTicket
|
||||
});
|
||||
} else {
|
||||
setScanResult({
|
||||
success: false,
|
||||
message: 'Ticket already used!',
|
||||
ticket
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setScanResult({
|
||||
success: false,
|
||||
message: 'Invalid Ticket ID',
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
setScanResult({
|
||||
success: false,
|
||||
message: 'Scan Error: Invalid QR code.',
|
||||
});
|
||||
}
|
||||
},
|
||||
() => {
|
||||
// console.warn(error);
|
||||
}
|
||||
);
|
||||
|
||||
return () => {
|
||||
scanner.clear().catch(error => {
|
||||
console.error("Failed to clear html5-qrcode scanner. ", error);
|
||||
});
|
||||
};
|
||||
}, [scanResult]);
|
||||
|
||||
const resetScanner = () => {
|
||||
setScanResult(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<div className="text-center mb-8">
|
||||
<h1 className="text-3xl font-bold mb-2">Scan Tickets</h1>
|
||||
<p className="text-slate-400">Use your camera to verify attendee tickets.</p>
|
||||
</div>
|
||||
|
||||
<div className="glass-panel p-6 overflow-hidden">
|
||||
{!scanResult ? (
|
||||
<div className="relative">
|
||||
<div id="reader" className="w-full rounded-lg overflow-hidden"></div>
|
||||
<p className="text-center text-sm text-slate-500 mt-4">
|
||||
Point camera at the QR code
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center py-8 animate-in fade-in zoom-in duration-300">
|
||||
{scanResult.success ? (
|
||||
<div className="text-green-500 mb-4 flex justify-center">
|
||||
<CheckCircle size={64} />
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-red-500 mb-4 flex justify-center">
|
||||
<XCircle size={64} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<h2 className="text-2xl font-bold mb-2">
|
||||
{scanResult.message}
|
||||
</h2>
|
||||
|
||||
{scanResult.ticket && (
|
||||
<div className="bg-slate-800/50 p-4 rounded-lg inline-block text-left mt-4 mb-6">
|
||||
<p className="text-slate-400 text-sm">Attendee</p>
|
||||
<p className="font-medium text-lg">{scanResult.ticket.attendeeName}</p>
|
||||
<p className="text-slate-400 text-sm mt-2">Type</p>
|
||||
<p className="font-medium text-lg">{scanResult.ticket.ticketType}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<button onClick={resetScanner} className="btn-primary">
|
||||
<RefreshCw size={18} />
|
||||
Scan Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
16
client/src/types/index.ts
Normal file
16
client/src/types/index.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export interface Event {
|
||||
id: string;
|
||||
name: string;
|
||||
date: string;
|
||||
location: string;
|
||||
}
|
||||
|
||||
export interface Ticket {
|
||||
id: string;
|
||||
eventId: string;
|
||||
attendeeName: string;
|
||||
attendeeEmail: string;
|
||||
ticketType: 'Klassenbester' | '1er Schüler' | 'Partyborner';
|
||||
status: 'valid' | 'used';
|
||||
createdAt: string;
|
||||
}
|
||||
69
client/src/utils/storage.ts
Normal file
69
client/src/utils/storage.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import type { Event, Ticket } from '../types';
|
||||
|
||||
const API_URL = '/api';
|
||||
|
||||
const getHeaders = () => {
|
||||
const token = sessionStorage.getItem('eventqr_token');
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
...(token ? { 'Authorization': `Bearer ${token}` } : {}),
|
||||
};
|
||||
};
|
||||
|
||||
export const getEvents = async (): Promise<Event[]> => {
|
||||
const response = await fetch(`${API_URL}/events`, { headers: getHeaders() });
|
||||
if (!response.ok) throw new Error('Failed to fetch events');
|
||||
return response.json();
|
||||
};
|
||||
|
||||
export const saveEvent = async (event: Omit<Event, 'id'>): Promise<Event> => {
|
||||
const response = await fetch(`${API_URL}/events`, {
|
||||
method: 'POST',
|
||||
headers: getHeaders(),
|
||||
body: JSON.stringify(event),
|
||||
});
|
||||
if (!response.ok) throw new Error('Failed to save event');
|
||||
return response.json();
|
||||
};
|
||||
|
||||
export const getTickets = async (eventId: string): Promise<Ticket[]> => {
|
||||
const response = await fetch(`${API_URL}/tickets?eventId=${eventId}`, { headers: getHeaders() });
|
||||
if (!response.ok) throw new Error('Failed to fetch tickets');
|
||||
return response.json();
|
||||
};
|
||||
|
||||
export const saveTicket = async (ticket: Omit<Ticket, 'id' | 'status' | 'createdAt'>): Promise<Ticket> => {
|
||||
const response = await fetch(`${API_URL}/tickets`, {
|
||||
method: 'POST',
|
||||
headers: getHeaders(),
|
||||
body: JSON.stringify(ticket),
|
||||
});
|
||||
if (!response.ok) throw new Error('Failed to save ticket');
|
||||
return response.json();
|
||||
};
|
||||
|
||||
export const resendTicketEmail = async (ticketId: string): Promise<void> => {
|
||||
const response = await fetch(`${API_URL}/tickets/${ticketId}/resend`, {
|
||||
method: 'POST',
|
||||
headers: getHeaders(),
|
||||
});
|
||||
if (!response.ok) throw new Error('Failed to resend ticket email');
|
||||
};
|
||||
|
||||
export const updateTicketStatus = async (ticketId: string, status: 'valid' | 'used'): Promise<Ticket> => {
|
||||
const response = await fetch(`${API_URL}/tickets/${ticketId}/status`, {
|
||||
method: 'PUT',
|
||||
headers: getHeaders(),
|
||||
body: JSON.stringify({ status }),
|
||||
});
|
||||
if (!response.ok) throw new Error('Failed to update ticket status');
|
||||
return response.json();
|
||||
};
|
||||
|
||||
export const deleteTicket = async (ticketId: string): Promise<void> => {
|
||||
const response = await fetch(`${API_URL}/tickets/${ticketId}`, {
|
||||
method: 'DELETE',
|
||||
headers: getHeaders(),
|
||||
});
|
||||
if (!response.ok) throw new Error('Failed to delete ticket');
|
||||
};
|
||||
11
client/tailwind.config.js
Normal file
11
client/tailwind.config.js
Normal file
@@ -0,0 +1,11 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: [
|
||||
"./index.html",
|
||||
"./src/**/*.{js,ts,jsx,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
28
client/tsconfig.app.json
Normal file
28
client/tsconfig.app.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"target": "ES2022",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"types": ["vite/client"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"erasableSyntaxOnly": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
7
client/tsconfig.json
Normal file
7
client/tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./tsconfig.app.json" },
|
||||
{ "path": "./tsconfig.node.json" }
|
||||
]
|
||||
}
|
||||
26
client/tsconfig.node.json
Normal file
26
client/tsconfig.node.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
"target": "ES2023",
|
||||
"lib": ["ES2023"],
|
||||
"module": "ESNext",
|
||||
"types": ["node"],
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"erasableSyntaxOnly": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
||||
15
client/vite.config.ts
Normal file
15
client/vite.config.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
server: {
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:3000',
|
||||
changeOrigin: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
6
dist/app.controller.d.ts
vendored
Normal file
6
dist/app.controller.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import { AppService } from './app.service';
|
||||
export declare class AppController {
|
||||
private readonly appService;
|
||||
constructor(appService: AppService);
|
||||
getHello(): string;
|
||||
}
|
||||
34
dist/app.controller.js
vendored
Normal file
34
dist/app.controller.js
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AppController = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const app_service_1 = require("./app.service");
|
||||
let AppController = class AppController {
|
||||
constructor(appService) {
|
||||
this.appService = appService;
|
||||
}
|
||||
getHello() {
|
||||
return this.appService.getHello();
|
||||
}
|
||||
};
|
||||
exports.AppController = AppController;
|
||||
__decorate([
|
||||
(0, common_1.Get)(),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", []),
|
||||
__metadata("design:returntype", String)
|
||||
], AppController.prototype, "getHello", null);
|
||||
exports.AppController = AppController = __decorate([
|
||||
(0, common_1.Controller)(),
|
||||
__metadata("design:paramtypes", [app_service_1.AppService])
|
||||
], AppController);
|
||||
//# sourceMappingURL=app.controller.js.map
|
||||
1
dist/app.controller.js.map
vendored
Normal file
1
dist/app.controller.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"app.controller.js","sourceRoot":"","sources":["../src/app.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAiD;AACjD,+CAA2C;AAGpC,IAAM,aAAa,GAAnB,MAAM,aAAa;IACxB,YAA6B,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAGvD,QAAQ;QACN,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;IACpC,CAAC;CACF,CAAA;AAPY,sCAAa;AAIxB;IADC,IAAA,YAAG,GAAE;;;;6CAGL;wBANU,aAAa;IADzB,IAAA,mBAAU,GAAE;qCAE8B,wBAAU;GADxC,aAAa,CAOzB"}
|
||||
2
dist/app.module.d.ts
vendored
Normal file
2
dist/app.module.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export declare class AppModule {
|
||||
}
|
||||
41
dist/app.module.js
vendored
Normal file
41
dist/app.module.js
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AppModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const config_1 = require("@nestjs/config");
|
||||
const serve_static_1 = require("@nestjs/serve-static");
|
||||
const path_1 = require("path");
|
||||
const app_controller_1 = require("./app.controller");
|
||||
const app_service_1 = require("./app.service");
|
||||
const prisma_module_1 = require("./prisma/prisma.module");
|
||||
const events_module_1 = require("./events/events.module");
|
||||
const tickets_module_1 = require("./tickets/tickets.module");
|
||||
const auth_module_1 = require("./auth/auth.module");
|
||||
const mail_module_1 = require("./mail/mail.module");
|
||||
let AppModule = class AppModule {
|
||||
};
|
||||
exports.AppModule = AppModule;
|
||||
exports.AppModule = AppModule = __decorate([
|
||||
(0, common_1.Module)({
|
||||
imports: [
|
||||
config_1.ConfigModule.forRoot({ isGlobal: true }),
|
||||
serve_static_1.ServeStaticModule.forRoot({
|
||||
rootPath: (0, path_1.join)(__dirname, '..', 'client', 'dist')
|
||||
}),
|
||||
prisma_module_1.PrismaModule,
|
||||
events_module_1.EventsModule,
|
||||
tickets_module_1.TicketsModule,
|
||||
auth_module_1.AuthModule,
|
||||
mail_module_1.MailModule,
|
||||
],
|
||||
controllers: [app_controller_1.AppController],
|
||||
providers: [app_service_1.AppService],
|
||||
})
|
||||
], AppModule);
|
||||
//# sourceMappingURL=app.module.js.map
|
||||
1
dist/app.module.js.map
vendored
Normal file
1
dist/app.module.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,2CAA8C;AAC9C,uDAAyD;AACzD,+BAA4B;AAC5B,qDAAiD;AACjD,+CAA2C;AAC3C,0DAAsD;AACtD,0DAAsD;AACtD,6DAAyD;AACzD,oDAAgD;AAChD,oDAAgD;AAiBzC,IAAM,SAAS,GAAf,MAAM,SAAS;CAAG,CAAA;AAAZ,8BAAS;oBAAT,SAAS;IAfrB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,qBAAY,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;YACxC,gCAAiB,CAAC,OAAO,CAAC;gBACxB,QAAQ,EAAE,IAAA,WAAI,EAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC;aAClD,CAAC;YACF,4BAAY;YACZ,4BAAY;YACZ,8BAAa;YACb,wBAAU;YACV,wBAAU;SACX;QACD,WAAW,EAAE,CAAC,8BAAa,CAAC;QAC5B,SAAS,EAAE,CAAC,wBAAU,CAAC;KACxB,CAAC;GACW,SAAS,CAAG"}
|
||||
3
dist/app.service.d.ts
vendored
Normal file
3
dist/app.service.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export declare class AppService {
|
||||
getHello(): string;
|
||||
}
|
||||
20
dist/app.service.js
vendored
Normal file
20
dist/app.service.js
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AppService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
let AppService = class AppService {
|
||||
getHello() {
|
||||
return 'Hello World!';
|
||||
}
|
||||
};
|
||||
exports.AppService = AppService;
|
||||
exports.AppService = AppService = __decorate([
|
||||
(0, common_1.Injectable)()
|
||||
], AppService);
|
||||
//# sourceMappingURL=app.service.js.map
|
||||
1
dist/app.service.js.map
vendored
Normal file
1
dist/app.service.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"app.service.js","sourceRoot":"","sources":["../src/app.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4C;AAGrC,IAAM,UAAU,GAAhB,MAAM,UAAU;IACrB,QAAQ;QACN,OAAO,cAAc,CAAC;IACxB,CAAC;CACF,CAAA;AAJY,gCAAU;qBAAV,UAAU;IADtB,IAAA,mBAAU,GAAE;GACA,UAAU,CAItB"}
|
||||
18
dist/assets/atiw-out-logo.svg
vendored
Normal file
18
dist/assets/atiw-out-logo.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 8.4 KiB |
13
dist/auth/auth.controller.d.ts
vendored
Normal file
13
dist/auth/auth.controller.d.ts
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { AuthService } from './auth.service';
|
||||
export declare class AuthController {
|
||||
private readonly authService;
|
||||
constructor(authService: AuthService);
|
||||
login(body: {
|
||||
password: string;
|
||||
}): Promise<{
|
||||
accessToken: string;
|
||||
}>;
|
||||
logout(): Promise<{
|
||||
success: boolean;
|
||||
}>;
|
||||
}
|
||||
49
dist/auth/auth.controller.js
vendored
Normal file
49
dist/auth/auth.controller.js
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthController = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const auth_service_1 = require("./auth.service");
|
||||
let AuthController = class AuthController {
|
||||
constructor(authService) {
|
||||
this.authService = authService;
|
||||
}
|
||||
async login(body) {
|
||||
return this.authService.login(body.password);
|
||||
}
|
||||
async logout() {
|
||||
return { success: true };
|
||||
}
|
||||
};
|
||||
exports.AuthController = AuthController;
|
||||
__decorate([
|
||||
(0, common_1.Post)('login'),
|
||||
(0, common_1.HttpCode)(common_1.HttpStatus.OK),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "login", null);
|
||||
__decorate([
|
||||
(0, common_1.Post)('logout'),
|
||||
(0, common_1.HttpCode)(common_1.HttpStatus.OK),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", []),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "logout", null);
|
||||
exports.AuthController = AuthController = __decorate([
|
||||
(0, common_1.Controller)(),
|
||||
__metadata("design:paramtypes", [auth_service_1.AuthService])
|
||||
], AuthController);
|
||||
//# sourceMappingURL=auth.controller.js.map
|
||||
1
dist/auth/auth.controller.js.map
vendored
Normal file
1
dist/auth/auth.controller.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.controller.js","sourceRoot":"","sources":["../../src/auth/auth.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA8E;AAC9E,iDAA6C;AAGtC,IAAM,cAAc,GAApB,MAAM,cAAc;IACzB,YAA6B,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;IAAG,CAAC;IAInD,AAAN,KAAK,CAAC,KAAK,CAAS,IAA0B;QAC5C,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAIK,AAAN,KAAK,CAAC,MAAM;QACV,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;CACF,CAAA;AAdY,wCAAc;AAKnB;IAFL,IAAA,aAAI,EAAC,OAAO,CAAC;IACb,IAAA,iBAAQ,EAAC,mBAAU,CAAC,EAAE,CAAC;IACX,WAAA,IAAA,aAAI,GAAE,CAAA;;;;2CAElB;AAIK;IAFL,IAAA,aAAI,EAAC,QAAQ,CAAC;IACd,IAAA,iBAAQ,EAAC,mBAAU,CAAC,EAAE,CAAC;;;;4CAGvB;yBAbU,cAAc;IAD1B,IAAA,mBAAU,GAAE;qCAE+B,0BAAW;GAD1C,cAAc,CAc1B"}
|
||||
2
dist/auth/auth.module.d.ts
vendored
Normal file
2
dist/auth/auth.module.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export declare class AuthModule {
|
||||
}
|
||||
38
dist/auth/auth.module.js
vendored
Normal file
38
dist/auth/auth.module.js
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const auth_service_1 = require("./auth.service");
|
||||
const auth_controller_1 = require("./auth.controller");
|
||||
const jwt_1 = require("@nestjs/jwt");
|
||||
const config_1 = require("@nestjs/config");
|
||||
const passport_1 = require("@nestjs/passport");
|
||||
const jwt_strategy_1 = require("./jwt.strategy");
|
||||
let AuthModule = class AuthModule {
|
||||
};
|
||||
exports.AuthModule = AuthModule;
|
||||
exports.AuthModule = AuthModule = __decorate([
|
||||
(0, common_1.Module)({
|
||||
imports: [
|
||||
config_1.ConfigModule,
|
||||
passport_1.PassportModule,
|
||||
jwt_1.JwtModule.registerAsync({
|
||||
imports: [config_1.ConfigModule],
|
||||
useFactory: async (configService) => ({
|
||||
secret: configService.get('JWT_SECRET') || 'secret',
|
||||
signOptions: { expiresIn: '1d' },
|
||||
}),
|
||||
inject: [config_1.ConfigService],
|
||||
}),
|
||||
],
|
||||
controllers: [auth_controller_1.AuthController],
|
||||
providers: [auth_service_1.AuthService, jwt_strategy_1.JwtStrategy],
|
||||
})
|
||||
], AuthModule);
|
||||
//# sourceMappingURL=auth.module.js.map
|
||||
1
dist/auth/auth.module.js.map
vendored
Normal file
1
dist/auth/auth.module.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,iDAA6C;AAC7C,uDAAmD;AACnD,qCAAwC;AACxC,2CAA6D;AAC7D,+CAAkD;AAClD,iDAA6C;AAkBtC,IAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,gCAAU;qBAAV,UAAU;IAhBtB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,qBAAY;YACZ,yBAAc;YACd,eAAS,CAAC,aAAa,CAAC;gBACtB,OAAO,EAAE,CAAC,qBAAY,CAAC;gBACvB,UAAU,EAAE,KAAK,EAAE,aAA4B,EAAE,EAAE,CAAC,CAAC;oBACnD,MAAM,EAAE,aAAa,CAAC,GAAG,CAAS,YAAY,CAAC,IAAI,QAAQ;oBAC3D,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE;iBACjC,CAAC;gBACF,MAAM,EAAE,CAAC,sBAAa,CAAC;aACxB,CAAC;SACH;QACD,WAAW,EAAE,CAAC,gCAAc,CAAC;QAC7B,SAAS,EAAE,CAAC,0BAAW,EAAE,0BAAW,CAAC;KACtC,CAAC;GACW,UAAU,CAAG"}
|
||||
10
dist/auth/auth.service.d.ts
vendored
Normal file
10
dist/auth/auth.service.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
export declare class AuthService {
|
||||
private jwtService;
|
||||
private configService;
|
||||
constructor(jwtService: JwtService, configService: ConfigService);
|
||||
login(password: string): Promise<{
|
||||
accessToken: string;
|
||||
}>;
|
||||
}
|
||||
38
dist/auth/auth.service.js
vendored
Normal file
38
dist/auth/auth.service.js
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const jwt_1 = require("@nestjs/jwt");
|
||||
const config_1 = require("@nestjs/config");
|
||||
let AuthService = class AuthService {
|
||||
constructor(jwtService, configService) {
|
||||
this.jwtService = jwtService;
|
||||
this.configService = configService;
|
||||
}
|
||||
async login(password) {
|
||||
const envPassword = this.configService.get('PASSWORD');
|
||||
if (password !== envPassword) {
|
||||
throw new common_1.UnauthorizedException('Incorrect password');
|
||||
}
|
||||
const payload = { username: 'admin', sub: 'admin' };
|
||||
return {
|
||||
accessToken: this.jwtService.sign(payload),
|
||||
};
|
||||
}
|
||||
};
|
||||
exports.AuthService = AuthService;
|
||||
exports.AuthService = AuthService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [jwt_1.JwtService,
|
||||
config_1.ConfigService])
|
||||
], AuthService);
|
||||
//# sourceMappingURL=auth.service.js.map
|
||||
1
dist/auth/auth.service.js.map
vendored
Normal file
1
dist/auth/auth.service.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../src/auth/auth.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAmE;AACnE,qCAAyC;AACzC,2CAA+C;AAGxC,IAAM,WAAW,GAAjB,MAAM,WAAW;IACtB,YACU,UAAsB,EACtB,aAA4B;QAD5B,eAAU,GAAV,UAAU,CAAY;QACtB,kBAAa,GAAb,aAAa,CAAe;IACnC,CAAC;IAEJ,KAAK,CAAC,KAAK,CAAC,QAAgB;QAC1B,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,UAAU,CAAC,CAAC;QAC/D,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;YAC7B,MAAM,IAAI,8BAAqB,CAAC,oBAAoB,CAAC,CAAC;QACxD,CAAC;QACD,MAAM,OAAO,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;QACpD,OAAO;YACL,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;SAC3C,CAAC;IACJ,CAAC;CACF,CAAA;AAhBY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAGW,gBAAU;QACP,sBAAa;GAH3B,WAAW,CAgBvB"}
|
||||
13
dist/auth/jwt.strategy.d.ts
vendored
Normal file
13
dist/auth/jwt.strategy.d.ts
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Strategy } from 'passport-jwt';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
declare const JwtStrategy_base: new (...args: [opt: import("passport-jwt").StrategyOptionsWithRequest] | [opt: import("passport-jwt").StrategyOptionsWithoutRequest]) => Strategy & {
|
||||
validate(...args: any[]): unknown;
|
||||
};
|
||||
export declare class JwtStrategy extends JwtStrategy_base {
|
||||
constructor(configService: ConfigService);
|
||||
validate(payload: any): Promise<{
|
||||
userId: any;
|
||||
username: any;
|
||||
}>;
|
||||
}
|
||||
export {};
|
||||
34
dist/auth/jwt.strategy.js
vendored
Normal file
34
dist/auth/jwt.strategy.js
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.JwtStrategy = void 0;
|
||||
const passport_jwt_1 = require("passport-jwt");
|
||||
const passport_1 = require("@nestjs/passport");
|
||||
const common_1 = require("@nestjs/common");
|
||||
const config_1 = require("@nestjs/config");
|
||||
let JwtStrategy = class JwtStrategy extends (0, passport_1.PassportStrategy)(passport_jwt_1.Strategy) {
|
||||
constructor(configService) {
|
||||
super({
|
||||
jwtFromRequest: passport_jwt_1.ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
ignoreExpiration: false,
|
||||
secretOrKey: configService.get('JWT_SECRET') || 'secret',
|
||||
});
|
||||
}
|
||||
async validate(payload) {
|
||||
return { userId: payload.sub, username: payload.username };
|
||||
}
|
||||
};
|
||||
exports.JwtStrategy = JwtStrategy;
|
||||
exports.JwtStrategy = JwtStrategy = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [config_1.ConfigService])
|
||||
], JwtStrategy);
|
||||
//# sourceMappingURL=jwt.strategy.js.map
|
||||
1
dist/auth/jwt.strategy.js.map
vendored
Normal file
1
dist/auth/jwt.strategy.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"jwt.strategy.js","sourceRoot":"","sources":["../../src/auth/jwt.strategy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+CAAoD;AACpD,+CAAoD;AACpD,2CAA4C;AAC5C,2CAA+C;AAGxC,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,IAAA,2BAAgB,EAAC,uBAAQ,CAAC;IACzD,YAAY,aAA4B;QACtC,KAAK,CAAC;YACJ,cAAc,EAAE,yBAAU,CAAC,2BAA2B,EAAE;YACxD,gBAAgB,EAAE,KAAK;YACvB,WAAW,EAAE,aAAa,CAAC,GAAG,CAAS,YAAY,CAAC,IAAI,QAAQ;SACjE,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAY;QACzB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC7D,CAAC;CACF,CAAA;AAZY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAEgB,sBAAa;GAD7B,WAAW,CAYvB"}
|
||||
5
dist/events/dto/create-event.dto.d.ts
vendored
Normal file
5
dist/events/dto/create-event.dto.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
export declare class CreateEventDto {
|
||||
name: string;
|
||||
date: string;
|
||||
location: string;
|
||||
}
|
||||
7
dist/events/dto/create-event.dto.js
vendored
Normal file
7
dist/events/dto/create-event.dto.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CreateEventDto = void 0;
|
||||
class CreateEventDto {
|
||||
}
|
||||
exports.CreateEventDto = CreateEventDto;
|
||||
//# sourceMappingURL=create-event.dto.js.map
|
||||
1
dist/events/dto/create-event.dto.js.map
vendored
Normal file
1
dist/events/dto/create-event.dto.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"create-event.dto.js","sourceRoot":"","sources":["../../../src/events/dto/create-event.dto.ts"],"names":[],"mappings":";;;AAAA,MAAa,cAAc;CAI1B;AAJD,wCAIC"}
|
||||
5
dist/events/dto/update-event.dto.d.ts
vendored
Normal file
5
dist/events/dto/update-event.dto.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { CreateEventDto } from './create-event.dto';
|
||||
declare const UpdateEventDto_base: import("@nestjs/mapped-types").MappedType<Partial<CreateEventDto>>;
|
||||
export declare class UpdateEventDto extends UpdateEventDto_base {
|
||||
}
|
||||
export {};
|
||||
9
dist/events/dto/update-event.dto.js
vendored
Normal file
9
dist/events/dto/update-event.dto.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.UpdateEventDto = void 0;
|
||||
const mapped_types_1 = require("@nestjs/mapped-types");
|
||||
const create_event_dto_1 = require("./create-event.dto");
|
||||
class UpdateEventDto extends (0, mapped_types_1.PartialType)(create_event_dto_1.CreateEventDto) {
|
||||
}
|
||||
exports.UpdateEventDto = UpdateEventDto;
|
||||
//# sourceMappingURL=update-event.dto.js.map
|
||||
1
dist/events/dto/update-event.dto.js.map
vendored
Normal file
1
dist/events/dto/update-event.dto.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"update-event.dto.js","sourceRoot":"","sources":["../../../src/events/dto/update-event.dto.ts"],"names":[],"mappings":";;;AAAA,uDAAmD;AACnD,yDAAoD;AAEpD,MAAa,cAAe,SAAQ,IAAA,0BAAW,EAAC,iCAAc,CAAC;CAAG;AAAlE,wCAAkE"}
|
||||
2
dist/events/entities/event.entity.d.ts
vendored
Normal file
2
dist/events/entities/event.entity.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export declare class Event {
|
||||
}
|
||||
7
dist/events/entities/event.entity.js
vendored
Normal file
7
dist/events/entities/event.entity.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Event = void 0;
|
||||
class Event {
|
||||
}
|
||||
exports.Event = Event;
|
||||
//# sourceMappingURL=event.entity.js.map
|
||||
1
dist/events/entities/event.entity.js.map
vendored
Normal file
1
dist/events/entities/event.entity.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"event.entity.js","sourceRoot":"","sources":["../../../src/events/entities/event.entity.ts"],"names":[],"mappings":";;;AAAA,MAAa,KAAK;CAAG;AAArB,sBAAqB"}
|
||||
18
dist/events/events.controller.d.ts
vendored
Normal file
18
dist/events/events.controller.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import { EventsService } from './events.service';
|
||||
import { CreateEventDto } from './dto/create-event.dto';
|
||||
export declare class EventsController {
|
||||
private readonly eventsService;
|
||||
constructor(eventsService: EventsService);
|
||||
create(createEventDto: CreateEventDto): import(".prisma/client").Prisma.Prisma__EventClient<{
|
||||
id: string;
|
||||
name: string;
|
||||
date: string;
|
||||
location: string;
|
||||
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
|
||||
findAll(): import(".prisma/client").Prisma.PrismaPromise<{
|
||||
id: string;
|
||||
name: string;
|
||||
date: string;
|
||||
location: string;
|
||||
}[]>;
|
||||
}
|
||||
48
dist/events/events.controller.js
vendored
Normal file
48
dist/events/events.controller.js
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.EventsController = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const events_service_1 = require("./events.service");
|
||||
const create_event_dto_1 = require("./dto/create-event.dto");
|
||||
let EventsController = class EventsController {
|
||||
constructor(eventsService) {
|
||||
this.eventsService = eventsService;
|
||||
}
|
||||
create(createEventDto) {
|
||||
return this.eventsService.create(createEventDto);
|
||||
}
|
||||
findAll() {
|
||||
return this.eventsService.findAll();
|
||||
}
|
||||
};
|
||||
exports.EventsController = EventsController;
|
||||
__decorate([
|
||||
(0, common_1.Post)(),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [create_event_dto_1.CreateEventDto]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], EventsController.prototype, "create", null);
|
||||
__decorate([
|
||||
(0, common_1.Get)(),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", []),
|
||||
__metadata("design:returntype", void 0)
|
||||
], EventsController.prototype, "findAll", null);
|
||||
exports.EventsController = EventsController = __decorate([
|
||||
(0, common_1.Controller)('events'),
|
||||
__metadata("design:paramtypes", [events_service_1.EventsService])
|
||||
], EventsController);
|
||||
//# sourceMappingURL=events.controller.js.map
|
||||
1
dist/events/events.controller.js.map
vendored
Normal file
1
dist/events/events.controller.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"events.controller.js","sourceRoot":"","sources":["../../src/events/events.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA6D;AAC7D,qDAAiD;AACjD,6DAAwD;AAGjD,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAC3B,YAA6B,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IAAG,CAAC;IAG7D,MAAM,CAAS,cAA8B;QAC3C,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IACnD,CAAC;IAGD,OAAO;QACL,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;IACtC,CAAC;CACF,CAAA;AAZY,4CAAgB;AAI3B;IADC,IAAA,aAAI,GAAE;IACC,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAiB,iCAAc;;8CAE5C;AAGD;IADC,IAAA,YAAG,GAAE;;;;+CAGL;2BAXU,gBAAgB;IAD5B,IAAA,mBAAU,EAAC,QAAQ,CAAC;qCAEyB,8BAAa;GAD9C,gBAAgB,CAY5B"}
|
||||
2
dist/events/events.module.d.ts
vendored
Normal file
2
dist/events/events.module.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export declare class EventsModule {
|
||||
}
|
||||
24
dist/events/events.module.js
vendored
Normal file
24
dist/events/events.module.js
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.EventsModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const events_service_1 = require("./events.service");
|
||||
const events_controller_1 = require("./events.controller");
|
||||
const prisma_module_1 = require("../prisma/prisma.module");
|
||||
let EventsModule = class EventsModule {
|
||||
};
|
||||
exports.EventsModule = EventsModule;
|
||||
exports.EventsModule = EventsModule = __decorate([
|
||||
(0, common_1.Module)({
|
||||
imports: [prisma_module_1.PrismaModule],
|
||||
controllers: [events_controller_1.EventsController],
|
||||
providers: [events_service_1.EventsService],
|
||||
})
|
||||
], EventsModule);
|
||||
//# sourceMappingURL=events.module.js.map
|
||||
1
dist/events/events.module.js.map
vendored
Normal file
1
dist/events/events.module.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"events.module.js","sourceRoot":"","sources":["../../src/events/events.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,qDAAiD;AACjD,2DAAuD;AACvD,2DAAuD;AAOhD,IAAM,YAAY,GAAlB,MAAM,YAAY;CAAG,CAAA;AAAf,oCAAY;uBAAZ,YAAY;IALxB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,4BAAY,CAAC;QACvB,WAAW,EAAE,CAAC,oCAAgB,CAAC;QAC/B,SAAS,EAAE,CAAC,8BAAa,CAAC;KAC3B,CAAC;GACW,YAAY,CAAG"}
|
||||
18
dist/events/events.service.d.ts
vendored
Normal file
18
dist/events/events.service.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import { CreateEventDto } from './dto/create-event.dto';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
export declare class EventsService {
|
||||
private prisma;
|
||||
constructor(prisma: PrismaService);
|
||||
create(createEventDto: CreateEventDto): import(".prisma/client").Prisma.Prisma__EventClient<{
|
||||
id: string;
|
||||
name: string;
|
||||
date: string;
|
||||
location: string;
|
||||
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
|
||||
findAll(): import(".prisma/client").Prisma.PrismaPromise<{
|
||||
id: string;
|
||||
name: string;
|
||||
date: string;
|
||||
location: string;
|
||||
}[]>;
|
||||
}
|
||||
31
dist/events/events.service.js
vendored
Normal file
31
dist/events/events.service.js
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.EventsService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const prisma_service_1 = require("../prisma/prisma.service");
|
||||
let EventsService = class EventsService {
|
||||
constructor(prisma) {
|
||||
this.prisma = prisma;
|
||||
}
|
||||
create(createEventDto) {
|
||||
return this.prisma.event.create({ data: createEventDto });
|
||||
}
|
||||
findAll() {
|
||||
return this.prisma.event.findMany();
|
||||
}
|
||||
};
|
||||
exports.EventsService = EventsService;
|
||||
exports.EventsService = EventsService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [prisma_service_1.PrismaService])
|
||||
], EventsService);
|
||||
//# sourceMappingURL=events.service.js.map
|
||||
1
dist/events/events.service.js.map
vendored
Normal file
1
dist/events/events.service.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"events.service.js","sourceRoot":"","sources":["../../src/events/events.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAE5C,6DAAyD;AAGlD,IAAM,aAAa,GAAnB,MAAM,aAAa;IACxB,YAAoB,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;IAAG,CAAC;IAE7C,MAAM,CAAC,cAA8B;QACnC,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;IACtC,CAAC;CACF,CAAA;AAVY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;qCAEiB,8BAAa;GAD9B,aAAa,CAUzB"}
|
||||
2
dist/mail/mail.module.d.ts
vendored
Normal file
2
dist/mail/mail.module.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export declare class MailModule {
|
||||
}
|
||||
23
dist/mail/mail.module.js
vendored
Normal file
23
dist/mail/mail.module.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.MailModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const mail_service_1 = require("./mail.service");
|
||||
const config_1 = require("@nestjs/config");
|
||||
let MailModule = class MailModule {
|
||||
};
|
||||
exports.MailModule = MailModule;
|
||||
exports.MailModule = MailModule = __decorate([
|
||||
(0, common_1.Module)({
|
||||
imports: [config_1.ConfigModule],
|
||||
providers: [mail_service_1.MailService],
|
||||
exports: [mail_service_1.MailService],
|
||||
})
|
||||
], MailModule);
|
||||
//# sourceMappingURL=mail.module.js.map
|
||||
1
dist/mail/mail.module.js.map
vendored
Normal file
1
dist/mail/mail.module.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"mail.module.js","sourceRoot":"","sources":["../../src/mail/mail.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,iDAA6C;AAC7C,2CAA8C;AAOvC,IAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,gCAAU;qBAAV,UAAU;IALtB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,qBAAY,CAAC;QACvB,SAAS,EAAE,CAAC,0BAAW,CAAC;QACxB,OAAO,EAAE,CAAC,0BAAW,CAAC;KACvB,CAAC;GACW,UAAU,CAAG"}
|
||||
7
dist/mail/mail.service.d.ts
vendored
Normal file
7
dist/mail/mail.service.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
export declare class MailService {
|
||||
private configService;
|
||||
private transporter;
|
||||
constructor(configService: ConfigService);
|
||||
sendTicket(email: string, name: string, ticketId: string, eventName: string, qrCodeBuffer: Buffer): Promise<void>;
|
||||
}
|
||||
96
dist/mail/mail.service.js
vendored
Normal file
96
dist/mail/mail.service.js
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.MailService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const nodemailer = require("nodemailer");
|
||||
const config_1 = require("@nestjs/config");
|
||||
const path = require("path");
|
||||
let MailService = class MailService {
|
||||
constructor(configService) {
|
||||
this.configService = configService;
|
||||
this.transporter = nodemailer.createTransport({
|
||||
host: this.configService.get('SMTP_HOST'),
|
||||
port: this.configService.get('SMTP_PORT'),
|
||||
secure: this.configService.get('SMTP_SECURE') === 'true',
|
||||
auth: {
|
||||
user: this.configService.get('SMTP_USER'),
|
||||
pass: this.configService.get('SMTP_PASS'),
|
||||
},
|
||||
});
|
||||
}
|
||||
async sendTicket(email, name, ticketId, eventName, qrCodeBuffer) {
|
||||
const logoPath = path.join(process.cwd(), 'dist/assets/atiw-out-logo.svg');
|
||||
const firstName = name.split(' ')[0];
|
||||
await this.transporter.sendMail({
|
||||
from: this.configService.get('SMTP_FROM') || '"Event Team" <noreply@example.com>',
|
||||
to: email,
|
||||
subject: `Dein Ticket fürs ATIW OUT!`,
|
||||
html: `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; background-color: #f4f4f5; margin: 0; padding: 0; }
|
||||
.container { max-width: 600px; margin: 32px auto; background-color: #ffffff; border-radius: 8px; overflow: hidden; border: 1px solid rgba(0, 0, 0, 0.2); padding: 32px; }
|
||||
.header { background-color: #ffffff; text-align: center; }
|
||||
.logo { height: 150px;}
|
||||
.content {text-align: center; color: #333333; }
|
||||
.greeting { font-size: 32px; color: #18181b; }
|
||||
.text { font-size: 16px; line-height: 1.5; color: #52525b;}
|
||||
.qr-container { background-color: #f4f4f5; padding: 24px; border-radius: 12px; display: inline-block; margin: 32px 0px; }
|
||||
.footer { background-color: #fafafa; padding: 24px; text-align: center; font-size: 14px; color: #a1a1aa; border-top: 1px solid #e4e4e7; }
|
||||
.highlight { color: #2563eb; font-weight: 600; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<img src="cid:logo" alt="Logo" class="logo" />
|
||||
</div>
|
||||
<div class="content">
|
||||
<h2 class="greeting">Moin Max,</h2>
|
||||
<p class="text">Hier ist dein Ticket für das <strong>ATIW OUT</strong>!</p>
|
||||
<p class="text">Zeig diesen QR Code einfach am <strong>09.12.</strong> am Eingang vor.</p>
|
||||
|
||||
<div class="qr-container">
|
||||
<img src="cid:qrcode" width="200" height="200" alt="Dein Ticket QR Code" style="display: block;"/>
|
||||
</div>
|
||||
|
||||
<p class="text">Wir wünschen dir viel Spaß!</p>
|
||||
<p class="text">~FI231 & FS231</p>
|
||||
<p class="text" style="margin-top: 32px;">Bei Fragen oder Problemen komm bitte<br>zum Klassenraum <strong>E.07</strong> und frag nach <strong>Jason</strong></p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`,
|
||||
attachments: [
|
||||
{
|
||||
filename: 'qrcode.png',
|
||||
content: qrCodeBuffer,
|
||||
cid: 'qrcode',
|
||||
},
|
||||
{
|
||||
filename: 'logo.svg',
|
||||
path: logoPath,
|
||||
cid: 'logo',
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
};
|
||||
exports.MailService = MailService;
|
||||
exports.MailService = MailService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [config_1.ConfigService])
|
||||
], MailService);
|
||||
//# sourceMappingURL=mail.service.js.map
|
||||
1
dist/mail/mail.service.js.map
vendored
Normal file
1
dist/mail/mail.service.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"mail.service.js","sourceRoot":"","sources":["../../src/mail/mail.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,yCAAyC;AACzC,2CAA+C;AAC/C,6BAA6B;AAGtB,IAAM,WAAW,GAAjB,MAAM,WAAW;IAGtB,YAAoB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;QAC9C,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC,eAAe,CAAC;YAC5C,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,WAAW,CAAC;YACjD,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,WAAW,CAAC;YACjD,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,aAAa,CAAC,KAAK,MAAM;YAChE,IAAI,EAAE;gBACJ,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,WAAW,CAAC;gBACjD,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,WAAW,CAAC;aAClD;SACF,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU,CACd,KAAa,EACb,IAAY,EACZ,QAAgB,EAChB,SAAiB,EACjB,YAAoB;QAEpB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,+BAA+B,CAAC,CAAC;QAC3E,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAErC,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC;YAC9B,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,WAAW,CAAC,IAAI,oCAAoC;YACzF,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,4BAA4B;YACrC,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsCL;YACD,WAAW,EAAE;gBACX;oBACE,QAAQ,EAAE,YAAY;oBACtB,OAAO,EAAE,YAAY;oBACrB,GAAG,EAAE,QAAQ;iBACd;gBACD;oBACE,QAAQ,EAAE,UAAU;oBACpB,IAAI,EAAE,QAAQ;oBACd,GAAG,EAAE,MAAM;iBACZ;aACF;SACF,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AAlFY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAIwB,sBAAa;GAHrC,WAAW,CAkFvB"}
|
||||
1
dist/main.d.ts
vendored
Normal file
1
dist/main.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export {};
|
||||
14
dist/main.js
vendored
Normal file
14
dist/main.js
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const core_1 = require("@nestjs/core");
|
||||
const app_module_1 = require("./app.module");
|
||||
const common_1 = require("@nestjs/common");
|
||||
async function bootstrap() {
|
||||
const app = await core_1.NestFactory.create(app_module_1.AppModule);
|
||||
app.setGlobalPrefix('api');
|
||||
app.enableCors();
|
||||
app.useGlobalPipes(new common_1.ValidationPipe());
|
||||
await app.listen(process.env.PORT ?? 3000);
|
||||
}
|
||||
bootstrap();
|
||||
//# sourceMappingURL=main.js.map
|
||||
1
dist/main.js.map
vendored
Normal file
1
dist/main.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;AAAA,uCAA2C;AAC3C,6CAAyC;AACzC,2CAAgD;AAEhD,KAAK,UAAU,SAAS;IACtB,MAAM,GAAG,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,sBAAS,CAAC,CAAC;IAChD,GAAG,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC3B,GAAG,CAAC,UAAU,EAAE,CAAC;IACjB,GAAG,CAAC,cAAc,CAAC,IAAI,uBAAc,EAAE,CAAC,CAAC;IACzC,MAAM,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;AAC7C,CAAC;AACD,SAAS,EAAE,CAAC"}
|
||||
2
dist/prisma/prisma.module.d.ts
vendored
Normal file
2
dist/prisma/prisma.module.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export declare class PrismaModule {
|
||||
}
|
||||
22
dist/prisma/prisma.module.js
vendored
Normal file
22
dist/prisma/prisma.module.js
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.PrismaModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const prisma_service_1 = require("./prisma.service");
|
||||
let PrismaModule = class PrismaModule {
|
||||
};
|
||||
exports.PrismaModule = PrismaModule;
|
||||
exports.PrismaModule = PrismaModule = __decorate([
|
||||
(0, common_1.Global)(),
|
||||
(0, common_1.Module)({
|
||||
providers: [prisma_service_1.PrismaService],
|
||||
exports: [prisma_service_1.PrismaService],
|
||||
})
|
||||
], PrismaModule);
|
||||
//# sourceMappingURL=prisma.module.js.map
|
||||
1
dist/prisma/prisma.module.js.map
vendored
Normal file
1
dist/prisma/prisma.module.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"prisma.module.js","sourceRoot":"","sources":["../../src/prisma/prisma.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAgD;AAChD,qDAAiD;AAO1C,IAAM,YAAY,GAAlB,MAAM,YAAY;CAAG,CAAA;AAAf,oCAAY;uBAAZ,YAAY;IALxB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,SAAS,EAAE,CAAC,8BAAa,CAAC;QAC1B,OAAO,EAAE,CAAC,8BAAa,CAAC;KACzB,CAAC;GACW,YAAY,CAAG"}
|
||||
6
dist/prisma/prisma.service.d.ts
vendored
Normal file
6
dist/prisma/prisma.service.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import { OnModuleInit, OnModuleDestroy } from '@nestjs/common';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
export declare class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
|
||||
onModuleInit(): Promise<void>;
|
||||
onModuleDestroy(): Promise<void>;
|
||||
}
|
||||
24
dist/prisma/prisma.service.js
vendored
Normal file
24
dist/prisma/prisma.service.js
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.PrismaService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const client_1 = require("@prisma/client");
|
||||
let PrismaService = class PrismaService extends client_1.PrismaClient {
|
||||
async onModuleInit() {
|
||||
await this.$connect();
|
||||
}
|
||||
async onModuleDestroy() {
|
||||
await this.$disconnect();
|
||||
}
|
||||
};
|
||||
exports.PrismaService = PrismaService;
|
||||
exports.PrismaService = PrismaService = __decorate([
|
||||
(0, common_1.Injectable)()
|
||||
], PrismaService);
|
||||
//# sourceMappingURL=prisma.service.js.map
|
||||
1
dist/prisma/prisma.service.js.map
vendored
Normal file
1
dist/prisma/prisma.service.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"prisma.service.js","sourceRoot":"","sources":["../../src/prisma/prisma.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA2E;AAC3E,2CAA8C;AAGvC,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,qBAAY;IAC7C,KAAK,CAAC,YAAY;QAChB,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;IAC3B,CAAC;CACF,CAAA;AARY,sCAAa;wBAAb,aAAa;IADzB,IAAA,mBAAU,GAAE;GACA,aAAa,CAQzB"}
|
||||
6
dist/tickets/dto/create-ticket.dto.d.ts
vendored
Normal file
6
dist/tickets/dto/create-ticket.dto.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
export declare class CreateTicketDto {
|
||||
eventId: string;
|
||||
attendeeName: string;
|
||||
attendeeEmail: string;
|
||||
ticketType: string;
|
||||
}
|
||||
33
dist/tickets/dto/create-ticket.dto.js
vendored
Normal file
33
dist/tickets/dto/create-ticket.dto.js
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.CreateTicketDto = void 0;
|
||||
const class_validator_1 = require("class-validator");
|
||||
class CreateTicketDto {
|
||||
}
|
||||
exports.CreateTicketDto = CreateTicketDto;
|
||||
__decorate([
|
||||
(0, class_validator_1.IsString)(),
|
||||
__metadata("design:type", String)
|
||||
], CreateTicketDto.prototype, "eventId", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsString)(),
|
||||
__metadata("design:type", String)
|
||||
], CreateTicketDto.prototype, "attendeeName", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsEmail)(),
|
||||
__metadata("design:type", String)
|
||||
], CreateTicketDto.prototype, "attendeeEmail", void 0);
|
||||
__decorate([
|
||||
(0, class_validator_1.IsIn)(['Klassenbester', '1er Schüler', 'Partyborner']),
|
||||
__metadata("design:type", String)
|
||||
], CreateTicketDto.prototype, "ticketType", void 0);
|
||||
//# sourceMappingURL=create-ticket.dto.js.map
|
||||
1
dist/tickets/dto/create-ticket.dto.js.map
vendored
Normal file
1
dist/tickets/dto/create-ticket.dto.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"create-ticket.dto.js","sourceRoot":"","sources":["../../../src/tickets/dto/create-ticket.dto.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,qDAA0D;AAE1D,MAAa,eAAe;CAY3B;AAZD,0CAYC;AAVC;IADC,IAAA,0BAAQ,GAAE;;gDACK;AAGhB;IADC,IAAA,0BAAQ,GAAE;;qDACU;AAGrB;IADC,IAAA,yBAAO,GAAE;;sDACY;AAGtB;IADC,IAAA,sBAAI,EAAC,CAAC,eAAe,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;;mDACnC"}
|
||||
5
dist/tickets/dto/update-ticket.dto.d.ts
vendored
Normal file
5
dist/tickets/dto/update-ticket.dto.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import { CreateTicketDto } from './create-ticket.dto';
|
||||
declare const UpdateTicketDto_base: import("@nestjs/mapped-types").MappedType<Partial<CreateTicketDto>>;
|
||||
export declare class UpdateTicketDto extends UpdateTicketDto_base {
|
||||
}
|
||||
export {};
|
||||
9
dist/tickets/dto/update-ticket.dto.js
vendored
Normal file
9
dist/tickets/dto/update-ticket.dto.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.UpdateTicketDto = void 0;
|
||||
const mapped_types_1 = require("@nestjs/mapped-types");
|
||||
const create_ticket_dto_1 = require("./create-ticket.dto");
|
||||
class UpdateTicketDto extends (0, mapped_types_1.PartialType)(create_ticket_dto_1.CreateTicketDto) {
|
||||
}
|
||||
exports.UpdateTicketDto = UpdateTicketDto;
|
||||
//# sourceMappingURL=update-ticket.dto.js.map
|
||||
1
dist/tickets/dto/update-ticket.dto.js.map
vendored
Normal file
1
dist/tickets/dto/update-ticket.dto.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"update-ticket.dto.js","sourceRoot":"","sources":["../../../src/tickets/dto/update-ticket.dto.ts"],"names":[],"mappings":";;;AAAA,uDAAmD;AACnD,2DAAsD;AAEtD,MAAa,eAAgB,SAAQ,IAAA,0BAAW,EAAC,mCAAe,CAAC;CAAG;AAApE,0CAAoE"}
|
||||
2
dist/tickets/entities/ticket.entity.d.ts
vendored
Normal file
2
dist/tickets/entities/ticket.entity.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export declare class Ticket {
|
||||
}
|
||||
7
dist/tickets/entities/ticket.entity.js
vendored
Normal file
7
dist/tickets/entities/ticket.entity.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Ticket = void 0;
|
||||
class Ticket {
|
||||
}
|
||||
exports.Ticket = Ticket;
|
||||
//# sourceMappingURL=ticket.entity.js.map
|
||||
1
dist/tickets/entities/ticket.entity.js.map
vendored
Normal file
1
dist/tickets/entities/ticket.entity.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"ticket.entity.js","sourceRoot":"","sources":["../../../src/tickets/entities/ticket.entity.ts"],"names":[],"mappings":";;;AAAA,MAAa,MAAM;CAAG;AAAtB,wBAAsB"}
|
||||
53
dist/tickets/tickets.controller.d.ts
vendored
Normal file
53
dist/tickets/tickets.controller.d.ts
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
import { TicketsService } from './tickets.service';
|
||||
import { CreateTicketDto } from './dto/create-ticket.dto';
|
||||
export declare class TicketsController {
|
||||
private readonly ticketsService;
|
||||
constructor(ticketsService: TicketsService);
|
||||
create(createTicketDto: CreateTicketDto): Promise<{
|
||||
event: {
|
||||
id: string;
|
||||
name: string;
|
||||
date: string;
|
||||
location: string;
|
||||
};
|
||||
} & {
|
||||
id: string;
|
||||
eventId: string;
|
||||
attendeeName: string;
|
||||
attendeeEmail: string;
|
||||
ticketType: string;
|
||||
status: string;
|
||||
createdAt: Date;
|
||||
}>;
|
||||
findAll(eventId: string): import(".prisma/client").Prisma.PrismaPromise<{
|
||||
id: string;
|
||||
eventId: string;
|
||||
attendeeName: string;
|
||||
attendeeEmail: string;
|
||||
ticketType: string;
|
||||
status: string;
|
||||
createdAt: Date;
|
||||
}[]>;
|
||||
resendEmail(id: string): Promise<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
}>;
|
||||
updateStatus(id: string, status: string): import(".prisma/client").Prisma.Prisma__TicketClient<{
|
||||
id: string;
|
||||
eventId: string;
|
||||
attendeeName: string;
|
||||
attendeeEmail: string;
|
||||
ticketType: string;
|
||||
status: string;
|
||||
createdAt: Date;
|
||||
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
|
||||
remove(id: string): import(".prisma/client").Prisma.Prisma__TicketClient<{
|
||||
id: string;
|
||||
eventId: string;
|
||||
attendeeName: string;
|
||||
attendeeEmail: string;
|
||||
ticketType: string;
|
||||
status: string;
|
||||
createdAt: Date;
|
||||
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
|
||||
}
|
||||
80
dist/tickets/tickets.controller.js
vendored
Normal file
80
dist/tickets/tickets.controller.js
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TicketsController = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const tickets_service_1 = require("./tickets.service");
|
||||
const create_ticket_dto_1 = require("./dto/create-ticket.dto");
|
||||
let TicketsController = class TicketsController {
|
||||
constructor(ticketsService) {
|
||||
this.ticketsService = ticketsService;
|
||||
}
|
||||
create(createTicketDto) {
|
||||
return this.ticketsService.create(createTicketDto);
|
||||
}
|
||||
findAll(eventId) {
|
||||
return this.ticketsService.findAll(eventId);
|
||||
}
|
||||
resendEmail(id) {
|
||||
return this.ticketsService.resendEmail(id);
|
||||
}
|
||||
updateStatus(id, status) {
|
||||
return this.ticketsService.updateStatus(id, status);
|
||||
}
|
||||
remove(id) {
|
||||
return this.ticketsService.remove(id);
|
||||
}
|
||||
};
|
||||
exports.TicketsController = TicketsController;
|
||||
__decorate([
|
||||
(0, common_1.Post)(),
|
||||
__param(0, (0, common_1.Body)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [create_ticket_dto_1.CreateTicketDto]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], TicketsController.prototype, "create", null);
|
||||
__decorate([
|
||||
(0, common_1.Get)(),
|
||||
__param(0, (0, common_1.Query)('eventId')),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [String]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], TicketsController.prototype, "findAll", null);
|
||||
__decorate([
|
||||
(0, common_1.Post)(':id/resend'),
|
||||
__param(0, (0, common_1.Param)('id')),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [String]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], TicketsController.prototype, "resendEmail", null);
|
||||
__decorate([
|
||||
(0, common_1.Put)(':id/status'),
|
||||
__param(0, (0, common_1.Param)('id')),
|
||||
__param(1, (0, common_1.Body)('status')),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [String, String]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], TicketsController.prototype, "updateStatus", null);
|
||||
__decorate([
|
||||
(0, common_1.Delete)(':id'),
|
||||
__param(0, (0, common_1.Param)('id')),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [String]),
|
||||
__metadata("design:returntype", void 0)
|
||||
], TicketsController.prototype, "remove", null);
|
||||
exports.TicketsController = TicketsController = __decorate([
|
||||
(0, common_1.Controller)('tickets'),
|
||||
__metadata("design:paramtypes", [tickets_service_1.TicketsService])
|
||||
], TicketsController);
|
||||
//# sourceMappingURL=tickets.controller.js.map
|
||||
1
dist/tickets/tickets.controller.js.map
vendored
Normal file
1
dist/tickets/tickets.controller.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"tickets.controller.js","sourceRoot":"","sources":["../../src/tickets/tickets.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAwF;AACxF,uDAAmD;AACnD,+DAA0D;AAGnD,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAC5B,YAA6B,cAA8B;QAA9B,mBAAc,GAAd,cAAc,CAAgB;IAAG,CAAC;IAG/D,MAAM,CAAS,eAAgC;QAC7C,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IACrD,CAAC;IAGD,OAAO,CAAmB,OAAe;QACvC,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAGD,WAAW,CAAc,EAAU;QACjC,OAAO,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IAC7C,CAAC;IAGD,YAAY,CAAc,EAAU,EAAkB,MAAc;QAClE,OAAO,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACtD,CAAC;IAGD,MAAM,CAAc,EAAU;QAC5B,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACxC,CAAC;CACF,CAAA;AA3BY,8CAAiB;AAI5B;IADC,IAAA,aAAI,GAAE;IACC,WAAA,IAAA,aAAI,GAAE,CAAA;;qCAAkB,mCAAe;;+CAE9C;AAGD;IADC,IAAA,YAAG,GAAE;IACG,WAAA,IAAA,cAAK,EAAC,SAAS,CAAC,CAAA;;;;gDAExB;AAGD;IADC,IAAA,aAAI,EAAC,YAAY,CAAC;IACN,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;;;;oDAEvB;AAGD;IADC,IAAA,YAAG,EAAC,YAAY,CAAC;IACJ,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;IAAc,WAAA,IAAA,aAAI,EAAC,QAAQ,CAAC,CAAA;;;;qDAEpD;AAGD;IADC,IAAA,eAAM,EAAC,KAAK,CAAC;IACN,WAAA,IAAA,cAAK,EAAC,IAAI,CAAC,CAAA;;;;+CAElB;4BA1BU,iBAAiB;IAD7B,IAAA,mBAAU,EAAC,SAAS,CAAC;qCAEyB,gCAAc;GADhD,iBAAiB,CA2B7B"}
|
||||
2
dist/tickets/tickets.module.d.ts
vendored
Normal file
2
dist/tickets/tickets.module.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export declare class TicketsModule {
|
||||
}
|
||||
25
dist/tickets/tickets.module.js
vendored
Normal file
25
dist/tickets/tickets.module.js
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TicketsModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const tickets_service_1 = require("./tickets.service");
|
||||
const tickets_controller_1 = require("./tickets.controller");
|
||||
const prisma_module_1 = require("../prisma/prisma.module");
|
||||
const mail_module_1 = require("../mail/mail.module");
|
||||
let TicketsModule = class TicketsModule {
|
||||
};
|
||||
exports.TicketsModule = TicketsModule;
|
||||
exports.TicketsModule = TicketsModule = __decorate([
|
||||
(0, common_1.Module)({
|
||||
imports: [prisma_module_1.PrismaModule, mail_module_1.MailModule],
|
||||
controllers: [tickets_controller_1.TicketsController],
|
||||
providers: [tickets_service_1.TicketsService],
|
||||
})
|
||||
], TicketsModule);
|
||||
//# sourceMappingURL=tickets.module.js.map
|
||||
1
dist/tickets/tickets.module.js.map
vendored
Normal file
1
dist/tickets/tickets.module.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"tickets.module.js","sourceRoot":"","sources":["../../src/tickets/tickets.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,uDAAmD;AACnD,6DAAyD;AACzD,2DAAuD;AACvD,qDAAiD;AAO1C,IAAM,aAAa,GAAnB,MAAM,aAAa;CAAG,CAAA;AAAhB,sCAAa;wBAAb,aAAa;IALzB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,4BAAY,EAAE,wBAAU,CAAC;QACnC,WAAW,EAAE,CAAC,sCAAiB,CAAC;QAChC,SAAS,EAAE,CAAC,gCAAc,CAAC;KAC5B,CAAC;GACW,aAAa,CAAG"}
|
||||
55
dist/tickets/tickets.service.d.ts
vendored
Normal file
55
dist/tickets/tickets.service.d.ts
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
import { CreateTicketDto } from './dto/create-ticket.dto';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { MailService } from '../mail/mail.service';
|
||||
export declare class TicketsService {
|
||||
private prisma;
|
||||
private mailService;
|
||||
constructor(prisma: PrismaService, mailService: MailService);
|
||||
create(createTicketDto: CreateTicketDto): Promise<{
|
||||
event: {
|
||||
id: string;
|
||||
name: string;
|
||||
date: string;
|
||||
location: string;
|
||||
};
|
||||
} & {
|
||||
id: string;
|
||||
eventId: string;
|
||||
attendeeName: string;
|
||||
attendeeEmail: string;
|
||||
ticketType: string;
|
||||
status: string;
|
||||
createdAt: Date;
|
||||
}>;
|
||||
findAll(eventId: string): import(".prisma/client").Prisma.PrismaPromise<{
|
||||
id: string;
|
||||
eventId: string;
|
||||
attendeeName: string;
|
||||
attendeeEmail: string;
|
||||
ticketType: string;
|
||||
status: string;
|
||||
createdAt: Date;
|
||||
}[]>;
|
||||
resendEmail(id: string): Promise<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
}>;
|
||||
updateStatus(id: string, status: string): import(".prisma/client").Prisma.Prisma__TicketClient<{
|
||||
id: string;
|
||||
eventId: string;
|
||||
attendeeName: string;
|
||||
attendeeEmail: string;
|
||||
ticketType: string;
|
||||
status: string;
|
||||
createdAt: Date;
|
||||
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
|
||||
remove(id: string): import(".prisma/client").Prisma.Prisma__TicketClient<{
|
||||
id: string;
|
||||
eventId: string;
|
||||
attendeeName: string;
|
||||
attendeeEmail: string;
|
||||
ticketType: string;
|
||||
status: string;
|
||||
createdAt: Date;
|
||||
}, never, import("@prisma/client/runtime/library").DefaultArgs, import(".prisma/client").Prisma.PrismaClientOptions>;
|
||||
}
|
||||
93
dist/tickets/tickets.service.js
vendored
Normal file
93
dist/tickets/tickets.service.js
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TicketsService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const prisma_service_1 = require("../prisma/prisma.service");
|
||||
const mail_service_1 = require("../mail/mail.service");
|
||||
const QRCode = require("qrcode");
|
||||
let TicketsService = class TicketsService {
|
||||
constructor(prisma, mailService) {
|
||||
this.prisma = prisma;
|
||||
this.mailService = mailService;
|
||||
}
|
||||
async create(createTicketDto) {
|
||||
const ticket = await this.prisma.ticket.create({
|
||||
data: createTicketDto,
|
||||
include: { event: true },
|
||||
});
|
||||
try {
|
||||
const qrCodeBuffer = await QRCode.toBuffer(ticket.id, {
|
||||
errorCorrectionLevel: 'H',
|
||||
type: 'png',
|
||||
width: 250,
|
||||
color: {
|
||||
dark: '#000000',
|
||||
light: '#FFFFFF',
|
||||
},
|
||||
});
|
||||
await this.mailService.sendTicket(ticket.attendeeEmail, ticket.attendeeName, ticket.id, ticket.event.name, qrCodeBuffer);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to send ticket email:', error);
|
||||
}
|
||||
return ticket;
|
||||
}
|
||||
findAll(eventId) {
|
||||
return this.prisma.ticket.findMany({
|
||||
where: { eventId },
|
||||
});
|
||||
}
|
||||
async resendEmail(id) {
|
||||
const ticket = await this.prisma.ticket.findUnique({
|
||||
where: { id },
|
||||
include: { event: true },
|
||||
});
|
||||
if (!ticket) {
|
||||
throw new Error('Ticket not found');
|
||||
}
|
||||
try {
|
||||
const qrCodeBuffer = await QRCode.toBuffer(ticket.id, {
|
||||
errorCorrectionLevel: 'H',
|
||||
type: 'png',
|
||||
width: 250,
|
||||
color: {
|
||||
dark: '#000000',
|
||||
light: '#FFFFFF',
|
||||
},
|
||||
});
|
||||
await this.mailService.sendTicket(ticket.attendeeEmail, ticket.attendeeName, ticket.id, ticket.event.name, qrCodeBuffer);
|
||||
return { success: true, message: 'Email resent successfully' };
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Failed to resend ticket email:', error);
|
||||
throw new Error('Failed to send email');
|
||||
}
|
||||
}
|
||||
updateStatus(id, status) {
|
||||
return this.prisma.ticket.update({
|
||||
where: { id },
|
||||
data: { status },
|
||||
});
|
||||
}
|
||||
remove(id) {
|
||||
return this.prisma.ticket.delete({
|
||||
where: { id },
|
||||
});
|
||||
}
|
||||
};
|
||||
exports.TicketsService = TicketsService;
|
||||
exports.TicketsService = TicketsService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [prisma_service_1.PrismaService,
|
||||
mail_service_1.MailService])
|
||||
], TicketsService);
|
||||
//# sourceMappingURL=tickets.service.js.map
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user