mirror of
https://github.com/polaroi8d/cactoide.git
synced 2026-03-22 06:05:28 +00:00
fix: refactor, docker, dateformatter
This commit is contained in:
43
Dockerfile
43
Dockerfile
@@ -1,47 +1,24 @@
|
||||
# Use Node.js 20 Alpine for smaller image size
|
||||
FROM node:20-alpine AS base
|
||||
|
||||
# Install dependencies only when needed
|
||||
FROM base AS deps
|
||||
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||
RUN apk add --no-cache libc6-compat
|
||||
FROM node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json .
|
||||
|
||||
# Install dependencies based on the preferred package manager
|
||||
COPY package.json package-lock.json* ./
|
||||
RUN npm ci
|
||||
|
||||
# Rebuild the source code only when needed
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
|
||||
# Build the application
|
||||
RUN npm run build
|
||||
RUN npm prune --production
|
||||
|
||||
FROM node:20-alpine
|
||||
|
||||
# Production image, copy all the files and run the app
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV production
|
||||
# Uncomment the following line in case you want to disable telemetry during runtime.
|
||||
# ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 sveltekit
|
||||
|
||||
# Copy the built application
|
||||
COPY --from=builder --chown=sveltekit:nodejs /app/build ./build
|
||||
COPY --from=builder --chown=sveltekit:nodejs /app/package.json ./package.json
|
||||
COPY --from=builder --chown=sveltekit:nodejs /app/node_modules ./node_modules
|
||||
|
||||
USER sveltekit
|
||||
COPY --from=builder /app/build build/
|
||||
COPY --from=builder /app/node_modules node_modules/
|
||||
COPY package.json .
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV PORT 3000
|
||||
ENV HOSTNAME "0.0.0.0"
|
||||
|
||||
# Start the application
|
||||
CMD ["node", "build"]
|
||||
ENV NODE_ENV production
|
||||
CMD [ "node", "build" ]
|
||||
|
||||
328
package-lock.json
generated
328
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,6 @@
|
||||
"@eslint/compat": "^1.2.5",
|
||||
"@eslint/js": "^9.18.0",
|
||||
"@sveltejs/adapter-auto": "^6.0.0",
|
||||
"@sveltejs/adapter-netlify": "^5.2.2",
|
||||
"@sveltejs/kit": "^2.22.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
||||
"@tailwindcss/forms": "^0.5.9",
|
||||
@@ -39,6 +38,7 @@
|
||||
"vite": "^7.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sveltejs/adapter-node": "^5.3.1",
|
||||
"drizzle-orm": "^0.44.5",
|
||||
"postgres": "^3.4.7"
|
||||
}
|
||||
|
||||
12
src/lib/dateFormatter.ts
Normal file
12
src/lib/dateFormatter.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export const formatDate = (dateString: string): string => {
|
||||
const date = new Date(dateString);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}/${month}/${day}`;
|
||||
};
|
||||
|
||||
export const formatTime = (timeString: string): string => {
|
||||
const [hours, minutes] = timeString.split(':');
|
||||
return `${hours}:${minutes}`;
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
export type EventType = 'limited' | 'unlimited';
|
||||
export type EventVisibility = 'public' | 'private';
|
||||
export type ActionType = 'add' | 'remove';
|
||||
|
||||
export interface Event {
|
||||
id: string;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import type { Event } from '$lib/types';
|
||||
import { goto } from '$app/navigation';
|
||||
import type { PageData } from '../$types';
|
||||
import { formatTime, formatDate } from '$lib/dateFormatter';
|
||||
|
||||
let publicEvents: Event[] = [];
|
||||
let error = '';
|
||||
@@ -9,19 +10,6 @@
|
||||
export let data: PageData;
|
||||
// Use the server-side data
|
||||
$: publicEvents = data.events;
|
||||
|
||||
function formatDate(dateString: string): string {
|
||||
const date = new Date(dateString);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}/${month}/${day}`;
|
||||
}
|
||||
|
||||
function formatTime(timeString: string): string {
|
||||
const [hours, minutes] = timeString.split(':');
|
||||
return `${hours}:${minutes}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { Event } from '$lib/types';
|
||||
import { goto } from '$app/navigation';
|
||||
import { formatTime, formatDate } from '$lib/dateFormatter';
|
||||
|
||||
export let data: { events: Event[] };
|
||||
|
||||
@@ -56,19 +57,6 @@
|
||||
showDeleteModal = false;
|
||||
eventToDelete = null;
|
||||
}
|
||||
|
||||
function formatDate(dateString: string): string {
|
||||
const date = new Date(dateString);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}/${month}/${day}`;
|
||||
}
|
||||
|
||||
function formatTime(timeString: string): string {
|
||||
const [hours, minutes] = timeString.split(':');
|
||||
return `${hours}:${minutes}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
||||
@@ -117,15 +117,14 @@ export const actions: Actions = {
|
||||
createdAt: new Date()
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
return { success: true, type: 'add' };
|
||||
} catch (err) {
|
||||
console.error('Error adding RSVP:', err);
|
||||
return fail(500, { error: 'Failed to add RSVP' });
|
||||
}
|
||||
},
|
||||
|
||||
removeRSVP: async ({ request, params }) => {
|
||||
const eventId = params.id;
|
||||
removeRSVP: async ({ request }) => {
|
||||
const formData = await request.formData();
|
||||
|
||||
const rsvpId = formData.get('rsvpId') as string;
|
||||
@@ -136,7 +135,7 @@ export const actions: Actions = {
|
||||
|
||||
try {
|
||||
await drizzleQuery.delete(rsvps).where(eq(rsvps.id, rsvpId));
|
||||
return { success: true };
|
||||
return { success: true, type: 'remove' };
|
||||
} catch (err) {
|
||||
console.error('Error removing RSVP:', err);
|
||||
return fail(500, { error: 'Failed to remove RSVP' });
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import type { Event, RSVP } from '$lib/types';
|
||||
import { goto } from '$app/navigation';
|
||||
import { enhance } from '$app/forms';
|
||||
import { formatTime, formatDate } from '$lib/dateFormatter';
|
||||
|
||||
export let data: { event: Event; rsvps: RSVP[]; userId: string };
|
||||
export let form;
|
||||
@@ -34,19 +35,6 @@
|
||||
|
||||
const eventId = $page.params.id;
|
||||
|
||||
function formatDate(dateString: string, timeString: string): string {
|
||||
const date = new Date(`${dateString}T${timeString}`);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}/${month}/${day}`;
|
||||
}
|
||||
|
||||
function formatTime(timeString: string): string {
|
||||
const [hours, minutes] = timeString.split(':');
|
||||
return `${hours}:${minutes}`;
|
||||
}
|
||||
|
||||
function copyEventLink() {
|
||||
const url = `${window.location.origin}/event/${eventId}`;
|
||||
navigator.clipboard.writeText(url).then(() => {
|
||||
@@ -329,11 +317,19 @@
|
||||
|
||||
<!-- Success/Error Messages -->
|
||||
{#if success}
|
||||
{#if form?.type === 'add'}
|
||||
<div
|
||||
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-green-500/30 bg-green-900/20 p-4 text-green-400"
|
||||
>
|
||||
{success}
|
||||
</div>
|
||||
{:else if form?.type === 'remove'}
|
||||
<div
|
||||
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-yellow-500/30 bg-yellow-900/20 p-4 text-yellow-400"
|
||||
>
|
||||
Removed RSVP successfully.
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if error}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import adapter from '@sveltejs/adapter-netlify';
|
||||
import adapter from '@sveltejs/adapter-node';
|
||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
@@ -15,7 +15,10 @@ const config = {
|
||||
// see "split" mode in https://github.com/sveltejs/kit/tree/main/packages/adapter-netlify
|
||||
edge: false,
|
||||
split: false
|
||||
})
|
||||
}),
|
||||
csrf: {
|
||||
checkOrigin: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -11,9 +11,4 @@
|
||||
"strict": true,
|
||||
"moduleResolution": "bundler"
|
||||
}
|
||||
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
|
||||
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
|
||||
//
|
||||
// To make changes to top-level options such as include and exclude, we recommend extending
|
||||
// the generated config; see https://svelte.dev/docs/kit/configuration#typescript
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user