Compare commits

...

2 Commits

Author SHA1 Message Date
c1a019a461 lint
All checks were successful
backend-action / build-image (push) Successful in 1m9s
2024-05-16 17:26:27 +07:00
5c4abf24bb added linting
added linting
2024-05-16 17:12:19 +07:00
16 changed files with 1997 additions and 126 deletions

10
.eslintrc.json Normal file
View File

@@ -0,0 +1,10 @@
{
"extends": [
"next/core-web-vitals",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"rules": {
"prefer-const": "error"
}
}

View File

@@ -1,9 +1,8 @@
"use client"; "use client";
import { LocationContext } from "@/components/locationContenxt"; import { LocationContext } from "@/components/locationContext";
import { useContext, useEffect, useState } from "react"; import { useContext, useState } from "react";
import Grouping from "./Grouping"; import Grouping from "./Grouping";
import { unique } from "drizzle-orm/mysql-core";
type Props = { type Props = {
allJobs: JobCategory[]; allJobs: JobCategory[];
@@ -19,10 +18,10 @@ type Group = {
jobs: number[]; jobs: number[];
}; };
export default function GroupCreator({ allJobs }: Props) { export default function GroupCreator({ allJobs }: Props) {
let locationContext = useContext(LocationContext); const locationContext = useContext(LocationContext);
let [usedJobs, setUsedJobs] = useState<number[]>([]); const [usedJobs, setUsedJobs] = useState<number[]>([]);
let [groups, setGroup] = useState<Group[]>( const [groups, setGroup] = useState<Group[]>(
[...Array(4).keys()].map((i) => ({ id: i + 1, jobs: [] })) [...Array(4).keys()].map((i) => ({ id: i + 1, jobs: [] })),
); );
function useJob(id: number) { function useJob(id: number) {
setUsedJobs((u) => [...u, id]); setUsedJobs((u) => [...u, id]);
@@ -37,13 +36,11 @@ export default function GroupCreator({ allJobs }: Props) {
groups.map((g) => { groups.map((g) => {
if (g.id != id) return g; if (g.id != id) return g;
else return { id, jobs }; else return { id, jobs };
}) }),
); );
} }
useEffect(() => { function submit() {} //TODO! submit group
console.log(groups);
}, [groups]);
if ( if (
locationContext?.zone[0] == undefined || locationContext?.zone[0] == undefined ||
@@ -66,7 +63,9 @@ export default function GroupCreator({ allJobs }: Props) {
))} ))}
<div className="flex justify-center"> <div className="flex justify-center">
<button className="bg-green-300 rounded-md p-2"></button> <button className="rounded-md bg-green-300 p-2" onClick={submit}>
</button>
</div> </div>
</div> </div>
); );

View File

@@ -14,10 +14,10 @@ export default function Grouping({
removeJob, removeJob,
updateGroup, updateGroup,
}: Props) { }: Props) {
let [selectedJob, setSelectedJob] = useState<JobCategory[]>([]); const [selectedJob, setSelectedJob] = useState<JobCategory[]>([]);
function addJob(id: string) { function addJob(id: string) {
let _id = parseInt(id); const _id = parseInt(id);
let job = availableJobs.find((j) => j.id == _id); const job = availableJobs.find((j) => j.id == _id);
if (job == undefined) return; if (job == undefined) return;
setSelectedJob((old) => [...old, job]); setSelectedJob((old) => [...old, job]);
selectJob(_id); selectJob(_id);
@@ -28,9 +28,9 @@ export default function Grouping({
} }
useEffect(() => { useEffect(() => {
updateGroup(selectedJob.map((j) => j.id)); updateGroup(selectedJob.map((j) => j.id));
}, [selectedJob]); }, [selectedJob, updateGroup]);
return ( return (
<div className="flex flex-col gap-2 m-2 p-2 border-black rounded-md shadow-md border w-full"> <div className="m-2 flex w-full flex-col gap-2 rounded-md border border-black p-2 shadow-md">
{selectedJob.map((j) => ( {selectedJob.map((j) => (
<div className="flex justify-between gap-2 p-2" key={j.id}> <div className="flex justify-between gap-2 p-2" key={j.id}>
<p>{j.name}</p> <p>{j.name}</p>

View File

@@ -1,13 +1,13 @@
import { db } from "@/src/db"; import { db } from "@/src/db";
import LocationSelector from "../../components/LocationSelector"; import LocationSelector from "../../components/LocationSelector";
import LocationContextProvider from "@/components/locationContenxt"; import LocationContextProvider from "@/components/locationContext";
import GroupCreator from "./GroupCreator"; import GroupCreator from "./GroupCreator";
export default async function Page() { export default async function Page() {
let provinces = await db.query.province const provinces = await db.query.province
.findMany({ with: { zones: true } }) .findMany({ with: { zones: true } })
.execute(); .execute();
let jobList = await db.query.group.findMany().execute(); const jobList = await db.query.group.findMany().execute();
return ( return (
<LocationContextProvider> <LocationContextProvider>
<LocationSelector provinces={provinces} /> <LocationSelector provinces={provinces} />

View File

@@ -5,16 +5,16 @@ type Props = {
}; };
export default function IdComponent({ updateIdList }: Props) { export default function IdComponent({ updateIdList }: Props) {
let [idSet, setIdSet] = useState<Set<string>>(new Set()); const [idSet, setIdSet] = useState<Set<string>>(new Set());
let onValidId = (id: string) => { const onValidId = (id: string) => {
setIdSet((prev) => new Set(prev.add(id))); setIdSet((prev) => new Set(prev.add(id)));
}; };
let removeCid = (id: string) => { const removeCid = (id: string) => {
setIdSet((prev) => new Set([...prev].filter((x) => x !== id))); setIdSet((prev) => new Set([...prev].filter((x) => x !== id)));
}; };
useEffect(() => { useEffect(() => {
updateIdList([...idSet]); updateIdList([...idSet]);
}, [idSet]); }, [idSet, updateIdList]);
return ( return (
<div className="flex justify-center"> <div className="flex justify-center">
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
@@ -37,7 +37,7 @@ function FixedId({ cid, removeCid }: FixedIdProps) {
<div className="flex gap-2"> <div className="flex gap-2">
<input type="text" className="border-2" disabled value={cid} /> <input type="text" className="border-2" disabled value={cid} />
<button <button
className="bg-red-300 p-2 rounded-md" className="rounded-md bg-red-300 p-2"
onClick={() => removeCid(cid)} onClick={() => removeCid(cid)}
> >
@@ -51,17 +51,17 @@ type SingleIdProps = {
}; };
function SingleIdComponent({ onValidId }: SingleIdProps) { function SingleIdComponent({ onValidId }: SingleIdProps) {
let [isValid, setIsValid] = useState(false); const [isValid, setIsValid] = useState(false);
let [cid, setCid] = useState(""); const [cid, setCid] = useState("");
useEffect(() => { useEffect(() => {
let isValidId = isValidThaiID(cid); const isValidId = isValidThaiID(cid);
setIsValid(isValidId); setIsValid(isValidId);
if (isValidId) { if (isValidId) {
onValidId(cid); onValidId(cid);
setCid(""); setCid("");
} }
}, [cid]); }, [cid, onValidId]);
return ( return (
<div className="flex gap-2"> <div className="flex gap-2">
<input <input

View File

@@ -3,16 +3,14 @@ import { useState } from "react";
import IdComponent from "./IdComponent"; import IdComponent from "./IdComponent";
export default function Page() { export default function Page() {
let [idList, setIdList] = useState<string[]>([]); const [idList, setIdList] = useState<string[]>([]);
function submit() { function submit() {} //TODO! submit inside user
console.log(idList);
}
return ( return (
<div> <div>
<IdComponent updateIdList={(cids) => setIdList(cids)} /> <IdComponent updateIdList={(cids) => setIdList(cids)} />
<p className="flex justify-center gap-4 mt-2 items-center"> <p className="mt-2 flex items-center justify-center gap-4">
Total: {idList.length}{" "} Total: {idList.length}{" "}
<button className="bg-green-200 p-2 rounded-md" onClick={submit}> <button className="rounded-md bg-green-200 p-2" onClick={submit}>
Submit Submit
</button> </button>
</p> </p>

View File

@@ -1,7 +1,7 @@
"use client"; "use client";
import { useContext, useEffect, useState } from "react"; import { useContext, useEffect, useState } from "react";
import { LocationContext } from "../locationContenxt"; import { LocationContext } from "../locationContext";
type Props = { type Props = {
provinces: Province[]; provinces: Province[];
@@ -17,20 +17,20 @@ type Zone = {
province: number; province: number;
}; };
export default function LocationSelector({ provinces }: Props) { export default function LocationSelector({ provinces }: Props) {
let [provinceId, setProvinceId] = useState<number | undefined>(undefined); const [provinceId, setProvinceId] = useState<number | undefined>(undefined);
let [amphurList, setAmphurList] = useState<Zone[] | undefined>(undefined); const [amphurList, setAmphurList] = useState<Zone[] | undefined>(undefined);
let [amphurId, setAmphurId] = useState<number | undefined>(undefined); const [amphurId, setAmphurId] = useState<number | undefined>(undefined);
const locationContext = useContext(LocationContext); const locationContext = useContext(LocationContext);
function setProvince(_id: string) { function setProvince(_id: string) {
let id = parseInt(_id); const id = parseInt(_id);
setProvinceId(id); setProvinceId(id);
let province = provinces.find((p) => p.id == id); const province = provinces.find((p) => p.id == id);
if (province == undefined) return; if (province == undefined) return;
setAmphurList(province.zones); setAmphurList(province.zones);
setAmphurId(undefined); setAmphurId(undefined);
} }
function setAmphur(_id: string) { function setAmphur(_id: string) {
let id = parseInt(_id); const id = parseInt(_id);
setAmphurId(id); setAmphurId(id);
} }
useEffect(() => { useEffect(() => {
@@ -43,7 +43,7 @@ export default function LocationSelector({ provinces }: Props) {
locationContext.zone[1](amphurId); locationContext.zone[1](amphurId);
locationContext.province[1](provinceId); locationContext.province[1](provinceId);
}, [amphurId]); }, [amphurId, locationContext, provinceId]);
return ( return (
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<div className="flex gap-2"> <div className="flex gap-2">

View File

@@ -13,7 +13,7 @@ type LocationContextType = {
}; };
export const LocationContext = createContext<LocationContextType | undefined>( export const LocationContext = createContext<LocationContextType | undefined>(
undefined undefined,
); );
export default function LocationContextProvider({ export default function LocationContextProvider({
@@ -21,8 +21,8 @@ export default function LocationContextProvider({
}: { }: {
children?: ReactNode; children?: ReactNode;
}) { }) {
let zone = useState<number | undefined>(undefined); const zone = useState<number | undefined>(undefined);
let province = useState<number | undefined>(undefined); const province = useState<number | undefined>(undefined);
return ( return (
<LocationContext.Provider value={{ zone, province }}> <LocationContext.Provider value={{ zone, province }}>

View File

@@ -9,6 +9,7 @@
"next-dev": "next dev", "next-dev": "next dev",
"start": "node dist/src/app.js", "start": "node dist/src/app.js",
"build": "swc src -d dist", "build": "swc src -d dist",
"lint": "next lint",
"initialize_data": "node -r @swc-node/register addMetadata.ts" "initialize_data": "node -r @swc-node/register addMetadata.ts"
}, },
"keywords": [], "keywords": [],
@@ -32,6 +33,7 @@
"zod": "^3.22.4" "zod": "^3.22.4"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.2.0",
"@swc-node/register": "^1.9.0", "@swc-node/register": "^1.9.0",
"@swc/cli": "^0.3.12", "@swc/cli": "^0.3.12",
"@swc/core": "^1.4.16", "@swc/core": "^1.4.16",
@@ -41,10 +43,17 @@
"@types/jsonwebtoken": "^9.0.6", "@types/jsonwebtoken": "^9.0.6",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"drizzle-kit": "^0.20.14", "drizzle-kit": "^0.20.14",
"eslint": "^8",
"eslint-config-next": "14.2.3",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
"nodemon": "^3.1.0", "nodemon": "^3.1.0",
"postcss": "^8.4.38", "postcss": "^8.4.38",
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.14",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"typescript": "^5.4.5" "typescript": "^5.4.5",
"typescript-eslint": "^7.9.0"
} }
} }

1906
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

6
prettier.config.mjs Normal file
View File

@@ -0,0 +1,6 @@
/** @type {import("prettier").Config} */
const config = {
plugins: ["prettier-plugin-tailwindcss"],
};
export default config;

View File

@@ -16,18 +16,18 @@ export function createClient() {
export async function createUploadImageUrl( export async function createUploadImageUrl(
mc: minio.Client, mc: minio.Client,
objectName: string, objectName: string,
contentType: string contentType: string,
) { ) {
let policy = mc.newPostPolicy(); const policy = mc.newPostPolicy();
policy.setKey(objectName); policy.setKey(objectName);
policy.setBucket(Config.bucketName); policy.setBucket(Config.bucketName);
let expires = new Date(); const expires = new Date();
expires.setSeconds(30 * 60); expires.setSeconds(30 * 60);
policy.setExpires(expires); policy.setExpires(expires);
policy.setContentType(contentType); policy.setContentType(contentType);
policy.setContentDisposition(`attachment; filename="${objectName}"`); policy.setContentDisposition(`attachment; filename="${objectName}"`);
policy.setContentLengthRange(1, 3 * 1024 * 1024); policy.setContentLengthRange(1, 3 * 1024 * 1024);
let rs = await mc.presignedPostPolicy(policy); const rs = await mc.presignedPostPolicy(policy);
return rs; return rs;
} }

View File

@@ -15,7 +15,7 @@ export const runPlayground = async (appRouter: AppRouter) => {
trpcApiEndpoint, trpcApiEndpoint,
playgroundEndpoint, playgroundEndpoint,
router: appRouter, router: appRouter,
}) }),
); );
app.listen(3001, () => { app.listen(3001, () => {

View File

@@ -41,7 +41,7 @@ export const user = sqliteTable(
(t) => ({ (t) => ({
phone_idx: index("phone_idx").on(t.phone), phone_idx: index("phone_idx").on(t.phone),
image_idx: index("image_idx").on(t.image), image_idx: index("image_idx").on(t.image),
}) }),
); );
export const userRelation = relations(user, ({ many, one }) => ({ export const userRelation = relations(user, ({ many, one }) => ({
@@ -98,7 +98,7 @@ export const userOpinion = sqliteTable(
}, },
(t) => ({ (t) => ({
pk: primaryKey({ columns: [t.userId, t.opinionId] }), pk: primaryKey({ columns: [t.userId, t.opinionId] }),
}) }),
); );
export const userOpinionRelation = relations(userOpinion, ({ one }) => ({ export const userOpinionRelation = relations(userOpinion, ({ one }) => ({
@@ -118,7 +118,7 @@ export const zone = sqliteTable(
.notNull() .notNull()
.references(() => province.id), .references(() => province.id),
}, },
(t) => ({ unique_name_province: unique().on(t.name, t.province) }) (t) => ({ unique_name_province: unique().on(t.name, t.province) }),
); );
export const zoneRelation = relations(zone, ({ one }) => ({ export const zoneRelation = relations(zone, ({ one }) => ({
province: one(province, { province: one(province, {
@@ -144,6 +144,6 @@ export const imageToUser = sqliteTable("image_to_user", {
.references(() => user.id), .references(() => user.id),
imageName: text("image_name").notNull(), imageName: text("image_name").notNull(),
createdOn: integer("created_on", { mode: "timestamp" }).default( createdOn: integer("created_on", { mode: "timestamp" }).default(
sql`CURRENT_TIMESTAMP` sql`CURRENT_TIMESTAMP`,
), ),
}); });

View File

@@ -42,7 +42,7 @@ export const createContext = async (opts: CreateHTTPContextOptions) => {
const bearerToken = authorizationHeader.split(" ")[1]; const bearerToken = authorizationHeader.split(" ")[1];
const phone = await verifyToken(bearerToken); const phone = await verifyToken(bearerToken);
if (phone !== null) { if (phone !== null) {
let user = await db.query.user.findFirst({ const user = await db.query.user.findFirst({
where: (user, { eq }) => eq(user.phone, phone), where: (user, { eq }) => eq(user.phone, phone),
}); });
return { return {
@@ -59,7 +59,7 @@ export const createContext = async (opts: CreateHTTPContextOptions) => {
async function verifyToken(token: string): Promise<string | null> { async function verifyToken(token: string): Promise<string | null> {
try { try {
let rs = await new Promise((resolve, reject) => { const rs = await new Promise((resolve, reject) => {
jwt.verify(token, Config.jwt_secret, (err, decoded) => { jwt.verify(token, Config.jwt_secret, (err, decoded) => {
if (err) { if (err) {
reject(err); reject(err);
@@ -68,7 +68,7 @@ async function verifyToken(token: string): Promise<string | null> {
} }
}); });
}); });
let data = z const data = z
.object({ .object({
phone: z.string(), phone: z.string(),
}) })

View File

@@ -1,13 +1,6 @@
import { router, publicProcedure, protectedProcedure } from "./trpc"; import { router, publicProcedure, protectedProcedure } from "./trpc";
import { db } from "./db"; import { db } from "./db";
import { import { imageToUser, opinion, user, userOpinion, zone } from "./schema";
imageToUser,
opinion,
province,
user,
userOpinion,
zone,
} from "./schema";
import { createInsertSchema } from "drizzle-zod"; import { createInsertSchema } from "drizzle-zod";
import { z } from "zod"; import { z } from "zod";
import { SQL, and, count, eq, inArray, sql } from "drizzle-orm"; import { SQL, and, count, eq, inArray, sql } from "drizzle-orm";
@@ -47,10 +40,10 @@ export const userRoute = router({
.input( .input(
userInsertSchema.omit({ id: true }).extend({ userInsertSchema.omit({ id: true }).extend({
opinions: opinionInsertSchema, opinions: opinionInsertSchema,
}) }),
) )
.mutation( .mutation(
async ({ input }) => await createUser({ ...input }, input.opinions) async ({ input }) => await createUser({ ...input }, input.opinions),
), ),
// changeImage: protectedProcedure // changeImage: protectedProcedure
updateUser: protectedProcedure updateUser: protectedProcedure
@@ -60,7 +53,7 @@ export const userRoute = router({
.input(z.object({ userId: z.number() })) .input(z.object({ userId: z.number() }))
.mutation(async ({ input }) => await getUser(input.userId, false)), .mutation(async ({ input }) => await getUser(input.userId, false)),
getSelf: protectedProcedure.mutation( getSelf: protectedProcedure.mutation(
async ({ ctx }) => await getUser(ctx.user.id, true) async ({ ctx }) => await getUser(ctx.user.id, true),
), ),
login: publicProcedure login: publicProcedure
.input(z.object({ cid: z.string(), phone: z.string() })) .input(z.object({ cid: z.string(), phone: z.string() }))
@@ -69,7 +62,7 @@ export const userRoute = router({
.input(opinionUpdateSchema) .input(opinionUpdateSchema)
.mutation( .mutation(
async ({ input, ctx }) => async ({ input, ctx }) =>
await changeOpinion(input.opinionId, ctx.user.id, input.choice) await changeOpinion(input.opinionId, ctx.user.id, input.choice),
), ),
requestChangeImage: protectedProcedure requestChangeImage: protectedProcedure
.input(z.object({ imageName: z.string(), contentType: z.string() })) .input(z.object({ imageName: z.string(), contentType: z.string() }))
@@ -78,11 +71,11 @@ export const userRoute = router({
await requestChangeImage( await requestChangeImage(
ctx.user.id, ctx.user.id,
input.imageName, input.imageName,
input.contentType input.contentType,
) ),
), ),
confirmChangeImage: protectedProcedure.mutation( confirmChangeImage: protectedProcedure.mutation(
async ({ ctx }) => await confirmChangeImage(ctx.user.id, ctx.user.image) async ({ ctx }) => await confirmChangeImage(ctx.user.id, ctx.user.image),
), ),
getAllUser: protectedProcedure getAllUser: protectedProcedure
.input( .input(
@@ -93,7 +86,7 @@ export const userRoute = router({
zone: z.number().optional(), zone: z.number().optional(),
opinionCount: z.number().default(3), opinionCount: z.number().default(3),
province: z.number().optional(), province: z.number().optional(),
}) }),
) )
.query( .query(
async ({ input }) => async ({ input }) =>
@@ -103,8 +96,8 @@ export const userRoute = router({
input.opinionCount, input.opinionCount,
input.group, input.group,
input.zone, input.zone,
input.province input.province,
) ),
), ),
getAllUserCount: protectedProcedure getAllUserCount: protectedProcedure
.input( .input(
@@ -112,24 +105,24 @@ export const userRoute = router({
group: z.number().optional(), group: z.number().optional(),
zone: z.number().optional(), zone: z.number().optional(),
province: z.number().optional(), province: z.number().optional(),
}) }),
) )
.query( .query(
async ({ input }) => async ({ input }) =>
await getAllUserCount(input.group, input.zone, input.province) await getAllUserCount(input.group, input.zone, input.province),
), ),
}); });
async function getAllUserCount( async function getAllUserCount(
group?: number, group?: number,
zoneId?: number, zoneId?: number,
provinceId?: number provinceId?: number,
) { ) {
let zoneIds: number[] = await getZone(provinceId); const zoneIds: number[] = await getZone(provinceId);
if (provinceId && zoneIds.length === 0) { if (provinceId && zoneIds.length === 0) {
return []; return [];
} }
let conditions: SQL[] = []; const conditions: SQL[] = [];
if (group !== undefined) { if (group !== undefined) {
conditions.push(eq(user.group, group)); conditions.push(eq(user.group, group));
} }
@@ -152,13 +145,13 @@ async function getAllUser(
opinionLimit: number, opinionLimit: number,
group?: number, group?: number,
zoneId?: number, zoneId?: number,
provinceId?: number provinceId?: number,
) { ) {
let zoneIds: number[] = await getZone(provinceId); const zoneIds: number[] = await getZone(provinceId);
if (provinceId && zoneIds.length === 0) { if (provinceId && zoneIds.length === 0) {
return []; return [];
} }
let users = await db.query.user.findMany({ const users = await db.query.user.findMany({
with: { with: {
group: true, group: true,
opinions: { opinions: {
@@ -172,7 +165,7 @@ async function getAllUser(
offset, offset,
orderBy: sql`random()`, orderBy: sql`random()`,
where: (user, { eq, and }) => { where: (user, { eq, and }) => {
let conditions: SQL[] = []; const conditions: SQL[] = [];
if (group !== undefined) { if (group !== undefined) {
conditions.push(eq(user.group, group)); conditions.push(eq(user.group, group));
} }
@@ -195,7 +188,7 @@ async function getAllUser(
} }
async function getUser(userId: number, showPhone: boolean) { async function getUser(userId: number, showPhone: boolean) {
let user = await db.query.user.findFirst({ const user = await db.query.user.findFirst({
where: (user, { eq }) => eq(user.id, userId), where: (user, { eq }) => eq(user.id, userId),
with: { with: {
group: true, group: true,
@@ -221,13 +214,13 @@ async function getUser(userId: number, showPhone: boolean) {
async function createUser( async function createUser(
newUser: UserInsertSchema, newUser: UserInsertSchema,
opinions: OpinionInsertSchema opinions: OpinionInsertSchema,
) { ) {
try { try {
let result = ( const result = (
await db.insert(user).values(newUser).returning({ id: user.id }) await db.insert(user).values(newUser).returning({ id: user.id })
)[0]; )[0];
for (let op of opinions) { for (const op of opinions) {
await db.insert(userOpinion).values({ ...op, userId: result.id }); await db.insert(userOpinion).values({ ...op, userId: result.id });
} }
return { token: createJWT(newUser.phone) }; return { token: createJWT(newUser.phone) };
@@ -248,7 +241,7 @@ async function updateUser(userId: number, update: UserUpdateSchema) {
} }
async function login(cid: string, phone: string) { async function login(cid: string, phone: string) {
let user = await db.query.user.findFirst({ const user = await db.query.user.findFirst({
where: (user, { and, eq }) => and(eq(user.cid, cid), eq(user.phone, phone)), where: (user, { and, eq }) => and(eq(user.cid, cid), eq(user.phone, phone)),
}); });
if (user === undefined) { if (user === undefined) {
@@ -264,10 +257,10 @@ async function login(cid: string, phone: string) {
async function changeOpinion( async function changeOpinion(
opinionId: number, opinionId: number,
userId: number, userId: number,
opinionChoice: OpinionInsertSchema[0]["choice"] opinionChoice: OpinionInsertSchema[0]["choice"],
) { ) {
try { try {
let thisOpinion = await db const thisOpinion = await db
.select() .select()
.from(opinion) .from(opinion)
.where(eq(opinion.id, opinionId)) .where(eq(opinion.id, opinionId))
@@ -308,7 +301,7 @@ async function changeOpinion(
async function requestChangeImage( async function requestChangeImage(
userId: number, userId: number,
imageName: string, imageName: string,
contentType: string contentType: string,
) { ) {
const mc = createClient(); const mc = createClient();
// Check if the image is valid // Check if the image is valid
@@ -328,11 +321,11 @@ async function requestChangeImage(
}); });
} }
// Create a unique image name // Create a unique image name
let tryCount = 0; const tryCount = 0;
let objectName: string | null = null; let objectName: string | null = null;
while (tryCount < 3) { while (tryCount < 3) {
let imageName = `${generateRandomString()}.${extension}`; const imageName = `${generateRandomString()}.${extension}`;
let ok = await db const ok = await db
.select({ value: count(user.image) }) .select({ value: count(user.image) })
.from(user) .from(user)
.where(eq(user.image, imageName)) .where(eq(user.image, imageName))
@@ -356,14 +349,14 @@ async function requestChangeImage(
target: [imageToUser.userId], target: [imageToUser.userId],
set: { imageName: objectName }, set: { imageName: objectName },
}); });
let request = await createUploadImageUrl(mc, objectName, contentType); const request = await createUploadImageUrl(mc, objectName, contentType);
request.postURL = Config.minioPublicBucketEndpoint; request.postURL = Config.minioPublicBucketEndpoint;
return request; return request;
} }
async function confirmChangeImage(userId: number, oldImage: string | null) { async function confirmChangeImage(userId: number, oldImage: string | null) {
const mc = createClient(); const mc = createClient();
let rs = await db const rs = await db
.select({ imageName: imageToUser.imageName }) .select({ imageName: imageToUser.imageName })
.from(imageToUser) .from(imageToUser)
.where(eq(imageToUser.userId, userId)); .where(eq(imageToUser.userId, userId));
@@ -373,7 +366,7 @@ async function confirmChangeImage(userId: number, oldImage: string | null) {
code: "BAD_REQUEST", code: "BAD_REQUEST",
}); });
} }
let imageName = rs[0].imageName; const imageName = rs[0].imageName;
const isImageExist = await mc const isImageExist = await mc
.statObject(Config.bucketName, imageName) .statObject(Config.bucketName, imageName)
.then(() => true) .then(() => true)
@@ -384,7 +377,7 @@ async function confirmChangeImage(userId: number, oldImage: string | null) {
code: "BAD_REQUEST", code: "BAD_REQUEST",
}); });
} }
const promises: Promise<any>[] = []; const promises: Promise<void>[] = [];
if (oldImage) { if (oldImage) {
promises.push(mc.removeObject(Config.bucketName, oldImage).catch(() => {})); promises.push(mc.removeObject(Config.bucketName, oldImage).catch(() => {}));
} }