Compare commits

..

10 Commits

Author SHA1 Message Date
hamid zarghami 8033501068 dockerfile
Build and Deploy Docker Images / build_and_deploy (push) Has been cancelled
2026-06-01 12:18:05 +03:30
hamid zarghami 5d0f766928 color description 2026-02-16 10:24:35 +03:30
hamid zarghami b0d9ab8381 quality 100% 2026-02-03 14:44:59 +03:30
hamid zarghami 067af56189 redirect 2026-01-06 12:45:04 +03:30
hamid zarghami 1609f2be60 radiu group 2025-12-30 09:25:18 +03:30
hamid zarghami 0b9f0a347e fix security bug deploy 2025-12-16 11:21:07 +03:30
Mehdi Mehrmanesh bd515fc93a update deploy-cicd.yaml 2025-12-13 18:16:15 +03:30
hamid zarghami ed01f69de7 fix security bug 2025-12-13 15:38:58 +03:30
hamid zarghami 6cda6a3b9d new address danak 2025-10-29 11:56:10 +03:30
hamid zarghami 7f24cd4c1c add address 2025-10-25 15:45:31 +03:30
12 changed files with 6868 additions and 4194 deletions
+76 -10
View File
@@ -1,25 +1,46 @@
# --------------------
# Base
# --------------------
FROM node:22-alpine AS base FROM node:22-alpine AS base
# Change Alpine repo
RUN sed -i 's|https://dl-cdn.alpinelinux.org/alpine|https://mirror.de.velop.ir/alpine|g' /etc/apk/repositories
# Configure npm registry mirror (Liara)
ENV NPM_CONFIG_REGISTRY=https://package-mirror.liara.ir/repository/npm/
RUN npm config set registry https://package-mirror.liara.ir/repository/npm/
# Install tzdata to support timezone settings
RUN apk add --no-cache tzdata && \ RUN apk add --no-cache tzdata && \
cp /usr/share/zoneinfo/Asia/Tehran /etc/localtime && \ cp /usr/share/zoneinfo/Asia/Tehran /etc/localtime && \
echo "Asia/Tehran" > /etc/timezone echo "Asia/Tehran" > /etc/timezone
RUN npm install -g corepack
RUN corepack enable && corepack prepare pnpm@latest --activate
WORKDIR /app WORKDIR /app
# --------------------
# Dependencies
# --------------------
FROM base AS deps FROM base AS deps
RUN apk add --no-cache libc6-compat git
COPY package*.json ./
COPY pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --ignore-scripts
RUN apk add --no-cache libc6-compat git
COPY package.json package-lock.json ./
RUN npm ci --legacy-peer-deps --ignore-scripts --loglevel info
# --------------------
# Build
# --------------------
FROM base AS builder FROM base AS builder
WORKDIR /build WORKDIR /build
COPY --from=deps /app/node_modules ./node_modules COPY --from=deps /app/node_modules ./node_modules
COPY . . COPY . .
RUN pnpm build && pnpm install --prod --frozen-lockfile --ignore-scripts
RUN npm run build && \
npm ci --omit=dev --legacy-peer-deps --ignore-scripts --loglevel info
# --------------------
# Runtime
# --------------------
FROM base AS runner FROM base AS runner
WORKDIR /app WORKDIR /app
@@ -39,8 +60,53 @@ USER appuser
EXPOSE 3000 EXPOSE 3000
ENV PORT=3000 ENV PORT=3000
ENV HOSTNAME="0.0.0.0" ENV HOSTNAME="0.0.0.0"
ENV NEXT_PUBLIC_BASE_URL=https://api.danakcorp.com
ENV NEXT_PUBLIC_TOKEN_NAME=dsc_refresh_token
ENV NEXT_PUBLIC_TOKEN_NAME=dsc_token
CMD ["node", "server.js"] CMD ["node", "server.js"]
# FROM node:22-alpine AS base
# RUN apk add --no-cache tzdata && \
# cp /usr/share/zoneinfo/Asia/Tehran /etc/localtime && \
# echo "Asia/Tehran" > /etc/timezone
# RUN npm install -g corepack
# RUN corepack enable && corepack prepare pnpm@latest --activate
# WORKDIR /app
# FROM base AS deps
# RUN apk add --no-cache libc6-compat git
# COPY package*.json ./
# COPY pnpm-lock.yaml ./
# RUN pnpm install --frozen-lockfile --ignore-scripts
# FROM base AS builder
# WORKDIR /build
# COPY --from=deps /app/node_modules ./node_modules
# COPY . .
# RUN pnpm build && pnpm install --prod --frozen-lockfile --ignore-scripts
# FROM base AS runner
# WORKDIR /app
# ENV NODE_ENV=production
# ENV NEXT_TELEMETRY_DISABLED=1
# RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# RUN mkdir .next && chown appuser:appgroup .next
# COPY --from=builder --chown=appuser:appgroup /build/.next/standalone ./
# COPY --from=builder --chown=appuser:appgroup /build/.next/static ./.next/static
# COPY --from=builder --chown=appuser:appgroup /build/public ./public
# COPY --from=builder --chown=appuser:appgroup /build/package.json ./package.json
# USER appuser
# EXPOSE 3000
# ENV PORT=3000
# ENV HOSTNAME="0.0.0.0"
# ENV NEXT_PUBLIC_BASE_URL=https://api.danakcorp.com
# ENV NEXT_PUBLIC_TOKEN_NAME=dsc_refresh_token
# ENV NEXT_PUBLIC_TOKEN_NAME=dsc_token
# CMD ["node", "server.js"]
+6764
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -18,7 +18,7 @@
"iconsax-react": "^0.0.8", "iconsax-react": "^0.0.8",
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"moment-jalaali": "^0.10.4", "moment-jalaali": "^0.10.4",
"next": "15.2.3", "next": "^15.5.9",
"rc-rate": "^2.13.1", "rc-rate": "^2.13.1",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
@@ -39,9 +39,9 @@
"@types/react": "^19", "@types/react": "^19",
"@types/react-dom": "^19", "@types/react-dom": "^19",
"eslint": "^9", "eslint": "^9",
"eslint-config-next": "15.2.3", "eslint-config-next": "15.2.6",
"tailwindcss": "^4", "tailwindcss": "^4",
"typescript": "^5" "typescript": "^5"
}, },
"packageManager": "pnpm@9.15.9+sha512.68046141893c66fad01c079231128e9afb89ef87e2691d69e4d40eee228988295fd4682181bae55b58418c3a253bde65a505ec7c5f9403ece5cc3cd37dcf2531" "packageManager": "pnpm@10.12.4+sha512.5ea8b0deed94ed68691c9bad4c955492705c5eeb8a87ef86bc62c74a26b037b08ff9570f108b2e4dbd1dd1a9186fea925e527f141c648e85af45631074680184"
} }
-4163
View File
File diff suppressed because it is too large Load Diff
+9 -1
View File
@@ -85,7 +85,15 @@ const ContactForm = () => {
color='black' color='black'
/> />
<div className='text-sm'> <div className='text-sm'>
تهران - یوسف آباد - فتحی شقاقی - پلاک ۵ - واحد ۱۳ دفتر مرکزی: تهران - یوسف آباد - فتحی شقاقی - پلاک ۵ - واحد ۱۳ </div>
</div>
<div className='flex gap-4 mt-4 items-center'>
<Location
size={24}
color='black'
/>
<div className='text-sm'>
دفتر اراک: بلوار قدوسی - برج دماوند - بلوک A - طبقه هفتم - واحد ۲
</div> </div>
</div> </div>
</div> </div>
+2 -2
View File
@@ -39,7 +39,7 @@ const CreateReview: FC<Props> = ({ refetch, id }) => {
}, },
onError: (error: ErrorType) => { onError: (error: ErrorType) => {
if (error.response && 'status' in error.response && error.response.status === 401) { if (error.response && 'status' in error.response && error.response.status === 401) {
window.location.href = LOGIN_URL + '?redirect=' + window.location.href window.location.href = LOGIN_URL
} else { } else {
toast(error.response?.data?.error?.message?.[0] || 'An error occurred', 'error') toast(error.response?.data?.error?.message?.[0] || 'An error occurred', 'error')
} }
@@ -64,7 +64,7 @@ const CreateReview: FC<Props> = ({ refetch, id }) => {
</div> </div>
<div className='mt-6 flex justify-center'> <div className='mt-6 flex justify-center'>
<Link href={LOGIN_URL + '?redirect=' + window.location.href}> <Link href={LOGIN_URL}>
<Button <Button
label={'ورود | ثبت نام'} label={'ورود | ثبت نام'}
className='w-fit px-7' className='w-fit px-7'
+2 -1
View File
@@ -23,6 +23,7 @@ const HeroSection: FC = () => {
alt='banner' alt='banner'
width={1920} width={1920}
height={1080} height={1080}
quality={100}
className='w-full rounded-4xl object-cover xl:mt-14 mt-8 min-h-[210px] max-h-[500px]' className='w-full rounded-4xl object-cover xl:mt-14 mt-8 min-h-[210px] max-h-[500px]'
/> />
@@ -33,7 +34,7 @@ const HeroSection: FC = () => {
<Link href={item.link}> <Link href={item.link}>
<Button <Button
className='xl:mt-5 mt-2 !w-fit xl:px-10 px-5 h-8 xl:h-10 bg-white !text-black' className='xl:mt-5 mt-2 w-fit! xl:px-10 px-5 h-8 xl:h-10 bg-white !text-black'
label='بیشتر بدانید' label='بیشتر بدانید'
/> />
</Link> </Link>
+1 -1
View File
@@ -29,7 +29,7 @@ const ExpandableContent: FC<Props> = memo(({ html, collapsedHeightClass = 'max-h
<div <div
ref={containerRef} ref={containerRef}
className={clx( className={clx(
'relative text-[13px] text-description leading-6', 'relative text-[13px] leading-6',
!expanded && 'overflow-hidden', !expanded && 'overflow-hidden',
!expanded && collapsedHeightClass, !expanded && collapsedHeightClass,
)} )}
+3 -3
View File
@@ -13,12 +13,12 @@ type Props = {
const RadioGroup: FC<Props> = (props: Props) => { const RadioGroup: FC<Props> = (props: Props) => {
return ( return (
<div className='flex gap-5 items-center text-xs'> <div className='flex flex-wrap gap-5 items-center text-xs'>
{ {
props.items.map((item, index) => ( props.items.map((item, index) => (
<div key={index} className='flex gap-2 items-center'> <div key={index} className='flex flex-wrap gap-2 items-center'>
<Radio value={item.value} onChange={props.onChange} isActive={item.value === props.selected} /> <Radio value={item.value} onChange={props.onChange} isActive={item.value === props.selected} />
<div className='mt-0.5'> <div className='mt-0.5 whitespace-nowrap'>
{item.label} {item.label}
</div> </div>
</div> </div>
+1 -3
View File
@@ -1,7 +1,7 @@
'use client' 'use client'
import { IApiErrorRepsonse } from '@/types/error.types' import { IApiErrorRepsonse } from '@/types/error.types'
import { QueryClient, QueryClientProvider, HydrationBoundary, QueryCache } from '@tanstack/react-query' import { QueryClient, QueryClientProvider, QueryCache } from '@tanstack/react-query'
import { ReactNode, useState } from 'react' import { ReactNode, useState } from 'react'
import { removeToken } from './func' import { removeToken } from './func'
import { useSharedStore } from '@/shared/store/sharedStore' import { useSharedStore } from '@/shared/store/sharedStore'
@@ -27,9 +27,7 @@ export default function QueryProvider({ children }: { children: ReactNode }) {
return ( return (
<QueryClientProvider client={client}> <QueryClientProvider client={client}>
<HydrationBoundary state={{}}>
{children} {children}
</HydrationBoundary>
</QueryClientProvider> </QueryClientProvider>
) )
} }
+4 -4
View File
@@ -79,8 +79,8 @@ const Header: FC = () => {
{typeof window !== 'undefined' && ( {typeof window !== 'undefined' && (
(() => { (() => {
const currentUrl = window.location.href // const currentUrl = window.location.href
const profileLink = isLogin ? `${CONSOLE_URL}/dashboard` : `${LOGIN_URL}?redirect=${encodeURIComponent(currentUrl)}` const profileLink = isLogin ? `${CONSOLE_URL}/dashboard` : `${LOGIN_URL}`
return ( return (
<a href={profileLink} target='_blank' className='border-l-2 whitespace-nowrap border-[#D8DCE4] pl-4 flex gap-2'> <a href={profileLink} target='_blank' className='border-l-2 whitespace-nowrap border-[#D8DCE4] pl-4 flex gap-2'>
<Profile <Profile
@@ -129,8 +129,8 @@ const Header: FC = () => {
{typeof window !== 'undefined' && ( {typeof window !== 'undefined' && (
(() => { (() => {
const currentUrl = window.location.href // const currentUrl = window.location.href
const profileLink = isLogin ? `${CONSOLE_URL}/dashboard` : `${LOGIN_URL}?redirect=${encodeURIComponent(currentUrl)}` const profileLink = isLogin ? `${CONSOLE_URL}/dashboard` : `${LOGIN_URL}`
return ( return (
<a href={profileLink} target='_blank'> <a href={profileLink} target='_blank'>
<Profile <Profile
+1 -1
View File
@@ -107,7 +107,7 @@ const SideBar: FC = () => {
if (!isLogin) if (!isLogin)
return ( return (
<div className='flex-1 flex items-end justify-center px-12'> <div className='flex-1 flex items-end justify-center px-12'>
<Link className='w-full' href={`${LOGIN_URL}?redirect=${encodeURIComponent(window.location.href)}`}> <Link className='w-full' href={`${LOGIN_URL}`}>
<Button <Button
label='ورود | ثبت نام' label='ورود | ثبت نام'
/> />