main
Some checks failed
Deploy Frontend / build-and-deploy (push) Failing after 19h27m44s

This commit is contained in:
2026-02-07 01:52:31 +03:00
parent 73c2a2a2e7
commit a8236e8783
30 changed files with 94 additions and 168 deletions

45
.github/workflows/deploy-ui.yml vendored Normal file
View File

@@ -0,0 +1,45 @@
name: Deploy Frontend
run-name: ${{ gitea.actor }} is deploying frontend 🚀
on:
push:
branches:
- main
- master
jobs:
build-and-deploy:
runs-on: ubuntu-latest
container:
image: catthehacker/ubuntu:act-latest
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: Build and Push Docker Image
run: |
docker build \
--build-arg NEXT_PUBLIC_API_URL='${{ secrets.NEXT_PUBLIC_API_URL }}' \
--build-arg NEXT_PUBLIC_AUTH_REQUIRED='false' \
-t skript-ui .
- name: Stop and Remove Existing Container
run: |
docker stop ui-skript-container || true
docker rm ui-skript-container || true
- name: Run New Container
run: |
docker run -d \
--name ui-skript-container \
--restart unless-stopped \
--network gitea-server_gitea \
-p 1506:3000 \
-e NEXTAUTH_URL='${{ secrets.NEXTAUTH_URL }}' \
-e NEXTAUTH_SECRET='${{ secrets.NEXTAUTH_SECRET }}' \
-e INTERNAL_API_URL='http://backend-skript-container:3000' \
skript-ui
- name: Cleanup
run: docker image prune -f

46
Dockerfile Normal file
View File

@@ -0,0 +1,46 @@
# Base image
FROM node:20-alpine AS base
# Install dependencies only when needed
FROM base AS deps
WORKDIR /app
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 . .
# Pass build args as environment variables
ARG NEXT_PUBLIC_API_URL
ARG NEXT_PUBLIC_AUTH_REQUIRED
ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
ENV NEXT_PUBLIC_AUTH_REQUIRED=${NEXT_PUBLIC_AUTH_REQUIRED}
RUN npm run build
# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
# set hostname to localhost
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]

View File

@@ -2,6 +2,7 @@ import type { NextConfig } from "next";
import createNextIntlPlugin from "next-intl/plugin"; import createNextIntlPlugin from "next-intl/plugin";
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
output: 'standalone',
experimental: { experimental: {
optimizePackageImports: ["@chakra-ui/react"], optimizePackageImports: ["@chakra-ui/react"],
}, },
@@ -10,7 +11,7 @@ const nextConfig: NextConfig = {
return [ return [
{ {
source: "/api/backend/:path*", source: "/api/backend/:path*",
destination: "http://localhost:3000/api/:path*", destination: `${process.env.INTERNAL_API_URL || "http://localhost:3000"}/api/:path*`,
}, },
]; ];
}, },

1
package-lock.json generated
View File

@@ -5983,7 +5983,6 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@rtsao/scc": "^1.1.0", "@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9", "array-includes": "^3.1.9",

View File

@@ -1,16 +0,0 @@
import { apiRequest } from "@/lib/api/api-service";
import { ApiResponse } from "@/types/api-response";
import { GenerateScriptDto, GeneratedScriptResponse } from "./types";
const generateScript = (projectId: string, data: GenerateScriptDto) => {
return apiRequest<ApiResponse<GeneratedScriptResponse>>({
url: `/projects/${projectId}/writer/generate`,
client: "core",
method: "post",
data,
});
};
export const aiWriterService = {
generateScript,
};

View File

@@ -1,15 +0,0 @@
export interface GenerateScriptDto {
topic: string;
contentType: string;
targetAudience: string[];
speechStyle: string[];
targetDuration: string;
tone: string;
language: string;
includeInterviews?: boolean;
}
export interface GeneratedScriptResponse {
script: any[]; // ScriptSegment[]
seo: any;
}

View File

@@ -1,10 +0,0 @@
import { useMutation } from "@tanstack/react-query";
import { aiWriterService } from "./service";
import { GenerateScriptDto } from "./types";
export function useGenerateScript() {
return useMutation({
mutationFn: ({ projectId, data }: { projectId: string; data: GenerateScriptDto }) =>
aiWriterService.generateScript(projectId, data),
});
}

View File

@@ -3,7 +3,7 @@
* Import all services and hooks from this single file * Import all services and hooks from this single file
* *
* Usage: * Usage:
* import { authService, useLogin, adminRolesService, useGetAllRoles } from '@/lib/api/Example'; * import { authService, useLogin, adminRolesService, useGetAllRoles } from '@/lib/api/example';
*/ */
// Services // Services

View File

@@ -1,52 +0,0 @@
import { apiRequest } from "@/lib/api/api-service";
import { ApiResponse } from "@/types/api-response";
import { CreateProjectDto, Project, UpdateProjectDto } from "./types";
const getMyProjects = () => {
return apiRequest<ApiResponse<Project[]>>({
url: "/projects/my-projects",
client: "core", // or whatever specific client config
method: "get",
});
};
const createProject = (data: CreateProjectDto) => {
return apiRequest<ApiResponse<Project>>({
url: "/projects",
client: "core",
method: "post",
data,
});
};
const getProject = (id: string) => {
return apiRequest<ApiResponse<Project>>({
url: `/projects/${id}`,
client: "core",
method: "get",
});
};
const updateProject = (id: string, data: UpdateProjectDto) => {
return apiRequest<ApiResponse<Project>>({
url: `/projects/${id}`,
client: "core",
method: "put",
data,
});
};
const deleteProject = (id: string) => {
return apiRequest<ApiResponse<Project>>({
url: `/projects/${id}`,
client: "core",
method: "delete",
});
};
export const projectsService = {
getMyProjects,
createProject,
getProject,
updateProject,
deleteProject,
};

View File

@@ -1,24 +0,0 @@
export interface Project {
id: string;
userId: string;
topic: string;
contentType: string;
language: string;
targetDuration: string;
createdAt: string;
updatedAt: string;
// ... other fields matching backend Project model
}
export interface CreateProjectDto {
topic: string;
contentType: string;
targetAudience: string[];
speechStyle: string[];
targetDuration: string;
tone: string;
language: string;
includeInterviews?: boolean;
}
export interface UpdateProjectDto extends Partial<CreateProjectDto> { }

View File

@@ -1,48 +0,0 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { projectsService } from "./service";
import { CreateProjectDto, UpdateProjectDto } from "./types";
export const ProjectsQueryKeys = {
all: ["projects"] as const,
myProjects: () => [...ProjectsQueryKeys.all, "my-projects"] as const,
detail: (id: string) => [...ProjectsQueryKeys.all, "detail", id] as const,
};
export function useMyProjects() {
return useQuery({
queryKey: ProjectsQueryKeys.myProjects(),
queryFn: () => projectsService.getMyProjects(),
});
}
export function useProject(id: string) {
return useQuery({
queryKey: ProjectsQueryKeys.detail(id),
queryFn: () => projectsService.getProject(id),
enabled: !!id,
});
}
export function useCreateProject() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: CreateProjectDto) => projectsService.createProject(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ProjectsQueryKeys.myProjects() });
},
});
}
export function useUpdateProject() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, data }: { id: string; data: UpdateProjectDto }) =>
projectsService.updateProject(id, data),
onSuccess: (_, variables) => {
queryClient.invalidateQueries({ queryKey: ProjectsQueryKeys.detail(variables.id) });
queryClient.invalidateQueries({ queryKey: ProjectsQueryKeys.myProjects() });
},
});
}