Merge remote-tracking branch 'origin/main' into efril

This commit is contained in:
efrilm 2025-09-03 12:26:38 +07:00
commit eb38bd7f5c
14 changed files with 160 additions and 29 deletions

5
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

View File

@ -0,0 +1,7 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="Stylelint" enabled="true" level="ERROR" enabled_by_default="true" />
</profile>
</component>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/pos-dashboard-v2.iml" filepath="$PROJECT_DIR$/.idea/pos-dashboard-v2.iml" />
</modules>
</component>
</project>

12
.idea/pos-dashboard-v2.iml generated Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

52
Dockerfile Normal file
View File

@ -0,0 +1,52 @@
# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
# Build arguments for environment variables
ARG NEXT_PUBLIC_APP_URL
ARG NEXT_PUBLIC_DOCS_URL
ARG NEXT_PUBLIC_API_URL
ARG API_URL
ARG BASEPATH
ARG MAPBOX_ACCESS_TOKEN
# Set environment variables for build
ENV API_URL=$API_URL
ENV BASEPATH=$BASEPATH
ENV MAPBOX_ACCESS_TOKEN=$MAPBOX_ACCESS_TOKEN
ENV NEXT_PUBLIC_APP_URL=$NEXT_PUBLIC_APP_URL
ENV NEXT_PUBLIC_DOCS_URL=$NEXT_PUBLIC_DOCS_URL
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
# Copy all files first
COPY . .
# Install dependencies
RUN npm ci
# Build icons
RUN npm run build:icons
# Build the application without linting
RUN npm run build:no-lint
# Production stage
FROM node:18-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 8080
ENV PORT=8080
CMD ["node", "server.js"]

19
deployment.sh Normal file
View File

@ -0,0 +1,19 @@
#!/bin/bash
APP_NAME="apskel-frontend"
PORT="8080"
echo "🔄 Pulling latest code..."
git pull
echo "🐳 Building Docker image..."
docker build -t apskel-frontend .
docker stop $APP_NAME 2>/dev/null
docker rm $APP_NAME 2>/dev/null
docker run -d --name $APP_NAME \
-p 8080:$PORT \
$APP_NAME:latest
echo "✅ Deployment complete."

View File

@ -1,29 +1,34 @@
import type { NextConfig } from 'next' import type { NextConfig } from 'next'
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
output: 'standalone',
basePath: process.env.BASEPATH, basePath: process.env.BASEPATH,
redirects: async () => { eslint: {
return [ ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
},
redirects: async () => [
{ {
source: '/', source: '/',
destination: '/en/dashboards/overview', destination: '/en/dashboards/overview',
permanent: true, permanent: true,
locale: false locale: false,
}, },
{ {
source: '/:lang(en|fr|ar)', source: '/:lang(en|fr|ar)',
destination: '/:lang/dashboards/overview', destination: '/:lang/dashboards/overview',
permanent: true, permanent: true,
locale: false locale: false,
}, },
{ {
source: '/((?!(?:en|fr|ar|front-pages|favicon.ico)\\b)):path', source: '/((?!(?:en|fr|ar|front-pages|favicon.ico)\\b)):path',
destination: '/en/:path', destination: '/en/:path',
permanent: true, permanent: true,
locale: false locale: false,
}
]
} }
],
} }
export default nextConfig export default nextConfig

17
package-lock.json generated
View File

@ -25,6 +25,7 @@
"@fullcalendar/react": "6.1.15", "@fullcalendar/react": "6.1.15",
"@fullcalendar/timegrid": "6.1.15", "@fullcalendar/timegrid": "6.1.15",
"@hookform/resolvers": "3.9.1", "@hookform/resolvers": "3.9.1",
"@iconify/react": "^6.0.1",
"@mui/lab": "6.0.0-beta.19", "@mui/lab": "6.0.0-beta.19",
"@mui/material": "6.2.1", "@mui/material": "6.2.1",
"@mui/material-nextjs": "6.2.1", "@mui/material-nextjs": "6.2.1",
@ -1308,6 +1309,21 @@
"pathe": "^1.1.2" "pathe": "^1.1.2"
} }
}, },
"node_modules/@iconify/react": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@iconify/react/-/react-6.0.1.tgz",
"integrity": "sha512-fCocnAfiGXjrA0u7KkS3W/OQHNp9LRFICudvOtxmS3Mf7U92aDhP50wyzRbobZli51zYt9ksZ9g0J7H586XvOQ==",
"license": "MIT",
"dependencies": {
"@iconify/types": "^2.0.0"
},
"funding": {
"url": "https://github.com/sponsors/cyberalien"
},
"peerDependencies": {
"react": ">=16"
}
},
"node_modules/@iconify/tools": { "node_modules/@iconify/tools": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/@iconify/tools/-/tools-4.1.1.tgz", "resolved": "https://registry.npmjs.org/@iconify/tools/-/tools-4.1.1.tgz",
@ -1332,7 +1348,6 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
"integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@iconify/utils": { "node_modules/@iconify/utils": {

View File

@ -11,7 +11,8 @@
"lint:fix": "next lint --fix", "lint:fix": "next lint --fix",
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"", "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"",
"build:icons": "tsx src/assets/iconify-icons/bundle-icons-css.ts", "build:icons": "tsx src/assets/iconify-icons/bundle-icons-css.ts",
"removeI18n": "tsx src/remove-translation-scripts/index.ts" "removeI18n": "tsx src/remove-translation-scripts/index.ts",
"build:no-lint": "NEXT_DISABLE_ESLINT=true NEXT_DISABLE_TYPECHECK=true next build"
}, },
"dependencies": { "dependencies": {
"@emoji-mart/data": "1.2.1", "@emoji-mart/data": "1.2.1",
@ -30,6 +31,7 @@
"@fullcalendar/react": "6.1.15", "@fullcalendar/react": "6.1.15",
"@fullcalendar/timegrid": "6.1.15", "@fullcalendar/timegrid": "6.1.15",
"@hookform/resolvers": "3.9.1", "@hookform/resolvers": "3.9.1",
"@iconify/react": "^6.0.1",
"@mui/lab": "6.0.0-beta.19", "@mui/lab": "6.0.0-beta.19",
"@mui/material": "6.2.1", "@mui/material": "6.2.1",
"@mui/material-nextjs": "6.2.1", "@mui/material-nextjs": "6.2.1",

View File

@ -97,8 +97,8 @@ const HorizontalMenu = ({ dictionary }: { dictionary: Awaited<ReturnType<typeof
<MenuItem href={`/${locale}/dashboards/analytics`} icon={<i className='tabler-trending-up' />}> <MenuItem href={`/${locale}/dashboards/analytics`} icon={<i className='tabler-trending-up' />}>
{dictionary['navigation'].analytics} {dictionary['navigation'].analytics}
</MenuItem> </MenuItem>
<MenuItem href={`/${locale}/dashboards/ecommerce`} icon={<i className='tabler-shopping-cart' />}> <MenuItem href={`/${locale}/dashboards/inventory`} icon={<i className='tabler-shopping-cart' />}>
{dictionary['navigation'].eCommerce} {dictionary['navigation'].inventory}
</MenuItem> </MenuItem>
<MenuItem href={`/${locale}/dashboards/academy`} icon={<i className='tabler-school' />}> <MenuItem href={`/${locale}/dashboards/academy`} icon={<i className='tabler-school' />}>
{dictionary['navigation'].academy} {dictionary['navigation'].academy}

View File

@ -6,7 +6,7 @@ const getToken = () => {
} }
export const api = axios.create({ export const api = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_URL, baseURL: 'https://api-pos.apskel.id/api/v1',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}, },

View File

@ -151,7 +151,7 @@ const AdjustmentStockDrawer = (props: Props) => {
onChange={e => setFormData({ ...formData, items: [{ ...formData.items[0], item_type: e.target.value }] })} onChange={e => setFormData({ ...formData, items: [{ ...formData.items[0], item_type: e.target.value }] })}
> >
<MenuItem value='PRODUCT'>Product</MenuItem> <MenuItem value='PRODUCT'>Product</MenuItem>
<MenuItem value='IGREDIENT'>Ingredient</MenuItem> {/* <MenuItem value='IGREDIENT'>Ingredient</MenuItem> */}
</CustomTextField> </CustomTextField>
<Autocomplete <Autocomplete
options={options} options={options}

View File

@ -485,7 +485,7 @@ const ReportGeneratorComponent: React.FC<ReportGeneratorProps> = ({
</Box> </Box>
<InfoBox> <InfoBox>
<Typography variant='body2' sx={{ color: textSecondary }}> <Typography variant='body2' component='div' sx={{ color: textSecondary }}>
{labels.periodLabel || 'Periode:'}{' '} {labels.periodLabel || 'Periode:'}{' '}
<Chip <Chip
label={getPeriodText()} label={getPeriodText()}