feat:drone, cookies login dummy

This commit is contained in:
Rama Priyanto 2026-03-18 15:32:08 +07:00
parent 76f9af6b8d
commit fdb8fdb4a7
11 changed files with 172 additions and 3 deletions

42
.drone.yml Normal file
View File

@ -0,0 +1,42 @@
kind: pipeline
type: ssh
name: silancar-build-deploy
server:
host:
from_secret: ssh_host
user:
from_secret: ssh_user
ssh_key:
from_secret: ssh_key
steps:
- name: prepare repo
when:
branch:
- main
commands:
- rm -rf /opt/build/silancar
- mkdir -p /opt/build
- cd /opt/build
- git clone http://38.47.180.165:3000/humas/silancar.git
- name: build image
when:
branch:
- main
commands:
- docker login 38.47.180.165:3000 -u administrator -p HarborDockerImageRep0
- cd /opt/build/silancar
- docker build -t 38.47.180.165:3000/humas/silancar:$DRONE_BRANCH .
- docker push 38.47.180.165:3000/humas/silancar:$DRONE_BRANCH
- name: deploy
when:
branch:
- main
commands:
- docker pull 38.47.180.165:3000/humas/silancar:$DRONE_BRANCH
- docker stop web-silancar|| true
- docker rm web-silancar || true
- docker run -dt -p 4700:4000 --restart always --name web-silancar 38.47.180.165:3000/humas/silancar:$DRONE_BRANCH

34
Dockerfile Normal file
View File

@ -0,0 +1,34 @@
FROM node:23.5.0-alpine
ENV PORT=4000
ENV NODE_ENV=production
ENV NODE_OPTIONS="--max-old-space-size=4096"
RUN apk add --no-cache \
python3 \
make \
g++ \
git \
sqlite-dev
WORKDIR /usr/src/app
# Copy dependency files
COPY package.json package-lock.json ./
# Install dependencies
RUN npm install --legacy-peer-deps
# Copy source code
COPY . .
# Init DB (aman karena pakai || true)
RUN mkdir -p ./lib/db
RUN node scripts/init-db.js || true
# Build Next.js
RUN npm run build
EXPOSE 4000
CMD ["npm", "run", "start"]

View File

@ -5,6 +5,7 @@ import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import Link from "next/link" import Link from "next/link"
import { useRouter } from "next/navigation" import { useRouter } from "next/navigation"
import { setCookiesEncrypt } from "@/utils/globals"
type FormValues = { type FormValues = {
nrp: string nrp: string
@ -26,13 +27,16 @@ export default function SignInPage() {
}) })
const onSubmit = async (data: FormValues) => { const onSubmit = async (data: FormValues) => {
console.log("DATA LOGIN:", data)
await new Promise((res) => setTimeout(res, 1000)) await new Promise((res) => setTimeout(res, 1000))
if(data.nrp=="12345678"&&data.password=="P@ssw0rd.1") {
setCookiesEncrypt("status", "Login", { expires: 1 });
router.push("/dashboard") router.push("/dashboard")
} }
}
return ( return (
<form <form
onSubmit={handleSubmit(onSubmit)} onSubmit={handleSubmit(onSubmit)}

View File

@ -1,8 +1,11 @@
'use client'
import DashboardSideMenu from "@/components/layout/dashboard-side-menu" import DashboardSideMenu from "@/components/layout/dashboard-side-menu"
import Footer from "@/components/layout/footer" import Footer from "@/components/layout/footer"
import { PinIcon } from "lucide-react" import { getCookiesDecrypt } from "@/utils/globals"
import Image from "next/image" import Image from "next/image"
import Link from "next/link" import Link from "next/link"
import { useRouter } from "next/navigation"
import { useEffect } from "react"
const dummy = { name: "Andri2 Ferinata", plat: "B 14 QU" } const dummy = { name: "Andri2 Ferinata", plat: "B 14 QU" }
@ -19,6 +22,15 @@ const menu = [
] ]
export default function Dashboard() { export default function Dashboard() {
const login=getCookiesDecrypt("status")
const router=useRouter()
useEffect(()=>{
if(!login){
router.push("/auth/sign-in")
}
},[login,router])
return ( return (
<div className="grid grid-cols-3 px-12 py-16"> <div className="grid grid-cols-3 px-12 py-16">
<div className="col-span-2 flex flex-col pr-8"> <div className="col-span-2 flex flex-col pr-8">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -3,6 +3,15 @@ import { Geist_Mono, Inter, Roboto } from "next/font/google"
import "./globals.css" import "./globals.css"
import { ThemeProvider } from "@/components/theme-provider" import { ThemeProvider } from "@/components/theme-provider"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
import type { Metadata } from "next"
export const metadata: Metadata = {
title: "Silancar",
description: "Silancar Korlantas",
icons: {
icon: "/favicon.ico", // atau png
},
}
const inter = Inter({ subsets: ["latin"], variable: "--font-sans" }) const inter = Inter({ subsets: ["latin"], variable: "--font-sans" })

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

27
package-lock.json generated
View File

@ -8,9 +8,13 @@
"name": "silancar", "name": "silancar",
"version": "0.0.1", "version": "0.0.1",
"dependencies": { "dependencies": {
"@types/crypto-js": "^4.2.2",
"@types/js-cookie": "^3.0.6",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"crypto-js": "^4.2.0",
"embla-carousel-react": "^8.6.0", "embla-carousel-react": "^8.6.0",
"js-cookie": "^3.0.5",
"lucide-react": "^0.577.0", "lucide-react": "^0.577.0",
"next": "16.1.7", "next": "16.1.7",
"next-themes": "^0.4.6", "next-themes": "^0.4.6",
@ -3545,12 +3549,22 @@
"tslib": "^2.4.0" "tslib": "^2.4.0"
} }
}, },
"node_modules/@types/crypto-js": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz",
"integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ=="
},
"node_modules/@types/estree": { "node_modules/@types/estree": {
"version": "1.0.8", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
"dev": true "dev": true
}, },
"node_modules/@types/js-cookie": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz",
"integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ=="
},
"node_modules/@types/json-schema": { "node_modules/@types/json-schema": {
"version": "7.0.15", "version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
@ -4939,6 +4953,11 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/crypto-js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
},
"node_modules/cssesc": { "node_modules/cssesc": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@ -7305,6 +7324,14 @@
"url": "https://github.com/sponsors/panva" "url": "https://github.com/sponsors/panva"
} }
}, },
"node_modules/js-cookie": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
"engines": {
"node": ">=14"
}
},
"node_modules/js-tokens": { "node_modules/js-tokens": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",

View File

@ -12,9 +12,13 @@
"typecheck": "tsc --noEmit" "typecheck": "tsc --noEmit"
}, },
"dependencies": { "dependencies": {
"@types/crypto-js": "^4.2.2",
"@types/js-cookie": "^3.0.6",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"crypto-js": "^4.2.0",
"embla-carousel-react": "^8.6.0", "embla-carousel-react": "^8.6.0",
"js-cookie": "^3.0.5",
"lucide-react": "^0.577.0", "lucide-react": "^0.577.0",
"next": "16.1.7", "next": "16.1.7",
"next-themes": "^0.4.6", "next-themes": "^0.4.6",

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

37
utils/globals.tsx Normal file
View File

@ -0,0 +1,37 @@
import Cookies from "js-cookie"
import CryptoJS from "crypto-js"
export function setCookiesEncrypt<T>(
param: string,
data: T,
options?: Cookies.CookieAttributes
) {
const cookiesEncrypt = CryptoJS.AES.encrypt(
JSON.stringify(data),
`${param}_EncryptKey@silancar`
).toString()
Cookies.set(param, cookiesEncrypt, options)
}
export function getCookiesDecrypt<T>(param: string): T | null {
const cookiesEncrypt = Cookies.get(param)
try {
if (cookiesEncrypt) {
const bytes = CryptoJS.AES.decrypt(
cookiesEncrypt,
`${param}_EncryptKey@silancar`
)
const decrypted = bytes.toString(CryptoJS.enc.Utf8)
return JSON.parse(decrypted) as T
}
return null
} catch (e) {
console.error("Decrypt error:", e)
return null
}
}