diff --git a/public/assets/images/layout/modal_header_icon04.svg b/public/assets/images/layout/modal_header_icon04.svg new file mode 100644 index 0000000..ba32c97 --- /dev/null +++ b/public/assets/images/layout/modal_header_icon04.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/assets/images/sub/sale_toggle_btn.svg b/public/assets/images/sub/sale_toggle_btn.svg new file mode 100644 index 0000000..ad2504a --- /dev/null +++ b/public/assets/images/sub/sale_toggle_btn.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/assets/images/sub/sale_toggle_btn_white.svg b/public/assets/images/sub/sale_toggle_btn_white.svg new file mode 100644 index 0000000..3575065 --- /dev/null +++ b/public/assets/images/sub/sale_toggle_btn_white.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/api/auth.ts b/src/api/auth.ts new file mode 100644 index 0000000..00a415e --- /dev/null +++ b/src/api/auth.ts @@ -0,0 +1,22 @@ +'use server' + +import { sessionOptions } from '@/libs/session' +import type { SessionData } from '@/types/Auth' +import { getIronSession } from 'iron-session' +import { cookies } from 'next/headers' +import { redirect } from 'next/navigation' + +export const logout = async () => { + const cookieStore = await cookies() + const session = await getIronSession(cookieStore, sessionOptions) + + session.destroy() + return redirect('/login') +} + +export const getSession = async () => { + const cookieStore = await cookies() + const session = await getIronSession(cookieStore, sessionOptions) + + return session +} diff --git a/src/api/suitable.ts b/src/api/suitable.ts new file mode 100644 index 0000000..952f956 --- /dev/null +++ b/src/api/suitable.ts @@ -0,0 +1,107 @@ +import { database } from '@/data' +import { axiosInstance } from '@/libs/axios' + +export interface Suitable { + id?: number + product_name: string + manufacturer: string + roof_material: string + shape: string + support_roof_tile: string + support_roof_tile_memo: string + support_roof_bracket: string + support_roof_bracket_memo: string + yg_anchor: string + yg_anchor_memo: string + rg_roof_tile_part: string + rg_roof_tile_part_memo: string + dido_hunt_support_tile_2: string + dido_hunt_support_tile_2_memo: string + takashima_power_base: string + takashima_power_base_memo: string + takashima_tile_bracket: string + takashima_tile_bracket_memo: string + slate_bracket_4: string + slate_bracket_4_memo: string + slate_single_metal_bracket: string + slate_single_metal_bracket_memo: string + dido_hunt_short_rack_4: string + dido_hunt_short_rack_4_memo: string + takashima_slate_bracket_slate_single: string + takashima_slate_bracket_slate_single_memo: string + df_metal_bracket: string + df_metal_bracket_memo: string + slate_metal_bracket: string + slate_metal_bracket_memo: string + takashima_slate_bracket_metal_roof: string + takashima_slate_bracket_metal_roof_memo: string +} + +export const suitableApi = { + // getList: async (category?: string, keyword?: string): Promise => { + // let condition: any = {} + // if (category) { + // condition['category'] = category + // } + // if (keyword) { + // condition['keyword'] = { + // contains: keyword, + // } + // } + // console.log('🚀 ~ getList: ~ condition:', condition) + // const response = await axiosInstance(null).get('/api/suitable/list', { params: condition }) + // console.log('🚀 ~ getList: ~ response:', response) + // return response.data + // }, + // getCategory: async (): Promise => { + // const response = await axiosInstance(null).get('/api/suitable/category') + // console.log('🚀 ~ getCategory: ~ response:', response) + // return response.data + // }, + // getDetails: async (roofMaterial: string): Promise => { + // const response = await axiosInstance(null).get(`/api/suitable/details?roof-material=${roofMaterial}`) + // console.log('🚀 ~ getDetails: ~ response:', response) + // return response.data + // }, + // create: async () => { + // const suitableData: Suitable[] = [] + // database.forEach((item) => { + // suitableData.push({ + // product_name: item[0], + // manufacturer: item[1], + // roof_material: item[2], + // shape: item[3], + // support_roof_tile: item[4], + // support_roof_tile_memo: item[5], + // support_roof_bracket: item[6], + // support_roof_bracket_memo: item[7], + // yg_anchor: item[8], + // yg_anchor_memo: item[9], + // rg_roof_tile_part: item[10], + // rg_roof_tile_part_memo: item[11], + // dido_hunt_support_tile_2: item[12], + // dido_hunt_support_tile_2_memo: item[13], + // takashima_power_base: item[14], + // takashima_power_base_memo: item[15], + // takashima_tile_bracket: item[16], + // takashima_tile_bracket_memo: item[17], + // slate_bracket_4: item[18], + // slate_bracket_4_memo: item[19], + // slate_single_metal_bracket: item[20], + // slate_single_metal_bracket_memo: item[21], + // dido_hunt_short_rack_4: item[22], + // dido_hunt_short_rack_4_memo: item[23], + // takashima_slate_bracket_slate_single: item[24], + // takashima_slate_bracket_slate_single_memo: item[25], + // df_metal_bracket: item[26], + // df_metal_bracket_memo: item[27], + // slate_metal_bracket: item[28], + // slate_metal_bracket_memo: item[29], + // takashima_slate_bracket_metal_roof: item[30], + // takashima_slate_bracket_metal_roof_memo: item[31], + // }) + // }) + // const response = await axiosInstance(null).post('/api/suitable', suitableData) + // return response.data + // }, +} diff --git a/src/api/surveySales.ts b/src/api/surveySales.ts new file mode 100644 index 0000000..b17f053 --- /dev/null +++ b/src/api/surveySales.ts @@ -0,0 +1,127 @@ +import { axiosInstance } from '@/libs/axios' + +export interface SurveySalesBasicInfo { + id?: number + representative: string + store: string | null + construction_point: string | null + investigation_date: string | null + building_name: string | null + customer_name: string | null + post_code: string | null + address: string | null + address_detail: string | null + submission_status: boolean + submission_date?: string | null + detail_info?: SurveySalesDetailInfo | null +} + +export interface SurveySalesDetailInfo { + id?: number + contract_capacity: string | null + retail_company: string | null + supplementary_facilities: number | null + supplementary_facilities_etc: string | null + installation_system: number | null + installation_system_etc: string | null + construction_year: number | null + construction_year_etc: string | null + roof_material: number | null + roof_material_etc: string | null + roof_shape: number | null + roof_shape_etc: string | null + roof_slope: string | null + house_structure: number | null + house_structure_etc: string | null + rafter_material: number | null + rafter_material_etc: string | null + rafter_size: number | null + rafter_size_etc: string | null + rafter_pitch: number | null + rafter_pitch_etc: string | null + rafter_direction: number | null + open_field_plate_kind: number | null + open_field_plate_kind_etc: string | null + open_field_plate_thickness: string | null + leak_trace: boolean | null + waterproof_material: number | null + waterproof_material_etc: string | null + insulation_presence: number | null + insulation_presence_etc: string | null + structure_order: number | null + structure_order_etc: string | null + installation_availability: number | null + installation_availability_etc: string | null + memo: string | null +} + +export const surveySalesApi = { + create: async (data: SurveySalesBasicInfo): Promise => { + try { + const response = await axiosInstance(null).post('/api/survey-sales', data) + return response.data.id ?? 0 + } catch (error) { + console.error(error) + return 0 + } + }, + getList: async (): Promise => { + try { + const response = await axiosInstance(null).get('/api/survey-sales') + return response.data + } catch (error) { + console.error(error) + return [] + } + }, + getDetail: async (id: number): Promise => { + try { + const response = await axiosInstance(null).get(`/api/survey-sales/${id}`) + return response.data + } catch (error) { + console.error(error) + return null + } + }, + update: async (id: number, data: SurveySalesBasicInfo): Promise => { + try { + const response = await axiosInstance(null).put(`/api/survey-sales/${id}`, data) + return response.data + } catch (error) { + console.error(error) + return null + } + }, + delete: async (id: number, isDetail: boolean = false): Promise => { + try { + await axiosInstance(null).delete(`/api/survey-sales/${id}`, { + params: { + detail_id: isDetail ? id : undefined, + }, + }) + return true + } catch (error) { + throw error + } + }, + createDetail: async (surveyId: number, data: SurveySalesDetailInfo): Promise => { + try { + await axiosInstance(null).post(`/api/survey-sales/${surveyId}`, data) + return true + } catch (error) { + throw error + } + }, + confirm: async (id: number): Promise => { + try { + await axiosInstance(null).patch(`/api/survey-sales/${id}`) + return true + } catch (error) { + throw error + } + }, + // update: async (data: SurveySalesBasicInfo): Promise => { + // const response = await axiosInstance.put(`/api/survey-sales`, data) + // return response.data + // }, +} diff --git a/src/api/user.ts b/src/api/user.ts new file mode 100644 index 0000000..6b39cf0 --- /dev/null +++ b/src/api/user.ts @@ -0,0 +1,37 @@ +import { axiosInstance } from '@/libs/axios' + +export interface UserData { + username: string + email: string + password: string +} + +export interface User { + id: number + username: string + email: string + created_at: string + updated_at: string +} + +export interface LoginData { + username: string + password: string +} + +export const userApi = { + create: async (data: UserData): Promise => { + const response = await axiosInstance(null).post('/api/user/create', data) + return response.data + }, + + getList: async (): Promise => { + const response = await axiosInstance(null).get('/api/user/list') + return response.data + }, + + getUser: async (data: LoginData): Promise => { + const response = await axiosInstance(null).post(`/api/user`, data) + return response.data + }, +} diff --git a/src/app/api/survey-sale/[id]/route.ts b/src/app/api/survey-sale/[id]/route.ts index bf5afe4..04ccf2d 100644 --- a/src/app/api/survey-sale/[id]/route.ts +++ b/src/app/api/survey-sale/[id]/route.ts @@ -1,72 +1,73 @@ import { NextResponse } from 'next/server' -export async function POST(request: Request, context: { params: { id: string } }) { - const body = await request.json() - const { id } = await context.params +// export async function POST(request: Request, { params }: { params: { id: string } }) { +// const body = await request.json() +// const { id } = params - // @ts-ignore - const survey = await prisma.SD_SERVEY_SALES_BASIC_INFO.update({ - where: { id: Number(id) }, - data: { - detail_info: { - create: body, - }, - }, - }) - return NextResponse.json({ message: 'Survey detail created successfully' }) -} -export async function GET(request: Request, context: { params: { id: string } }) { - const { id } = await context.params - // @ts-ignore - const survey = await prisma.SD_SERVEY_SALES_BASIC_INFO.findUnique({ - where: { id: Number(id) }, - include: { - detail_info: true, - }, - }) - return NextResponse.json(survey) -} +// // @ts-ignore +// const survey = await prisma.SD_SERVEY_SALES_BASIC_INFO.update({ +// where: { id: Number(id) }, +// data: { +// detail_info: { +// create: body, +// }, +// }, +// }) +// return NextResponse.json({ message: 'Survey detail created successfully' }) +// } -export async function PUT(request: Request, context: { params: { id: string } }) { - const { id } = await context.params - const body = await request.json() - // @ts-ignore - const survey = await prisma.SD_SERVEY_SALES_BASIC_INFO.update({ - where: { id: Number(id) }, - data: { - ...body, - detail_info: { - update: body.detail_info, - }, - }, - }) - return NextResponse.json(survey) -} +// export async function GET(request: Request, { params }: { params: { id: string } }) { +// const { id } = params +// // @ts-ignore +// const survey = await prisma.SD_SERVEY_SALES_BASIC_INFO.findUnique({ +// where: { id: Number(id) }, +// include: { +// detail_info: true, +// }, +// }) +// return NextResponse.json(survey) +// } -export async function DELETE(request: Request, context: { params: { id: string; detail_id: string } }) { - const { id, detail_id } = await context.params - if (detail_id) { - // @ts-ignore - const survey = await prisma.SD_SERVEY_SALES_DETAIL_INFO.delete({ - where: { id: Number(detail_id) }, - }) - } else { - // @ts-ignore - const survey = await prisma.SD_SERVEY_SALES_BASIC_INFO.delete({ - where: { id: Number(id) }, - }) - } - return NextResponse.json({ message: 'Survey deleted successfully' }) -} +// export async function PUT(request: Request, { params }: { params: { id: string } }) { +// const { id } = params +// const body = await request.json() +// // @ts-ignore +// const survey = await prisma.SD_SERVEY_SALES_BASIC_INFO.update({ +// where: { id: Number(id) }, +// data: { +// ...body, +// detail_info: { +// update: body.detail_info, +// }, +// }, +// }) +// return NextResponse.json(survey) +// } -export async function PATCH(request: Request, context: { params: { id: string } }) { - const { id } = await context.params - // @ts-ignore - const survey = await prisma.SD_SERVEY_SALES_BASIC_INFO.update({ - where: { id: Number(id) }, - data: { - submission_status: true, - }, - }) - return NextResponse.json({ message: 'Survey confirmed successfully' }) -} +// export async function DELETE(request: Request, { params }: { params: { id: string; detail_id: string } }) { +// const { id, detail_id } = params +// if (detail_id) { +// // @ts-ignore +// const survey = await prisma.SD_SERVEY_SALES_DETAIL_INFO.delete({ +// where: { id: Number(detail_id) }, +// }) +// } else { +// // @ts-ignore +// const survey = await prisma.SD_SERVEY_SALES_BASIC_INFO.delete({ +// where: { id: Number(id) }, +// }) +// } +// return NextResponse.json({ message: 'Survey deleted successfully' }) +// } + +// export async function PATCH(request: Request, { params }: { params: { id: string } }) { +// const { id } = params +// // @ts-ignore +// const survey = await prisma.SD_SERVEY_SALES_BASIC_INFO.update({ +// where: { id: Number(id) }, +// data: { +// submission_status: true, +// }, +// }) +// return NextResponse.json({ message: 'Survey confirmed successfully' }) +// } diff --git a/src/app/api/user/route.ts b/src/app/api/user/route.ts index d3cda5f..0249fd6 100644 --- a/src/app/api/user/route.ts +++ b/src/app/api/user/route.ts @@ -2,7 +2,8 @@ import { NextResponse } from 'next/server' import { prisma } from '@/libs/prisma' import { getIronSession } from 'iron-session' import { cookies } from 'next/headers' -import { SessionData, sessionOptions } from '@/libs/session' +import { sessionOptions } from '@/libs/session' +import type { SessionData } from '@/types/Auth' export async function POST(request: Request) { const { username, password } = await request.json() @@ -25,8 +26,8 @@ export async function POST(request: Request) { const cookieStore = await cookies() const session = await getIronSession(cookieStore, sessionOptions) console.log('start session edit!') - session.username = user.username! - session.email = user.email! + // session.username = user.username! + // session.email = user.email! session.isLoggedIn = true console.log('end session edit!') await session.save() diff --git a/src/styles/base/_check-radio.scss b/src/styles/base/_check-radio.scss index d4d2904..47c50cb 100644 --- a/src/styles/base/_check-radio.scss +++ b/src/styles/base/_check-radio.scss @@ -85,6 +85,9 @@ input[type="checkbox"]:disabled + label::after{ cursor: default; } + input[type="checkbox"]:disabled:checked + label::before{ + background-color: #A8B6C7; + } &.ch-bld{ input[type="checkbox"]:checked + label{ font-weight: 500; diff --git a/src/styles/components/_sub.scss b/src/styles/components/_sub.scss index ebcb374..73c5fc4 100644 --- a/src/styles/components/_sub.scss +++ b/src/styles/components/_sub.scss @@ -77,36 +77,11 @@ } } } -.sale-detail-tab-relative{ - height: 40px; - margin-bottom: 10px; -} -.sale-detail-tab-wrap{ - position: fixed; - top: 66px; - left: 0; - width: 100%; - height: 40px; - background-color: $white-fff; - z-index: 98000; - .sale-detail-tab-inner{ - position: relative; - @include flex(0px); - align-items: center; - height: 100%; - .sale-detail-tab{ - flex: 1; - height: 100%; - background-color: #fff; - border-top: 1px solid #DDDFE2; - border-bottom: 1px solid #DDDFE2; - @include defaultFont($font-s-13, $font-w-500, $font-c); - &.act{ - color: $white-fff; - background-color: #5F738E; - border-color: #5F738E; - } - } +.sale-form-btn-wrap{ + padding: 20px 20px 0 ; + background-color: #fff; + .btn-flex-wrap{ + margin-top: 0; } } @@ -202,6 +177,11 @@ } // 매물 상세 +.sale-data-table-wrap{ + padding: 24px; + background-color: #fff; + border-top: 1px solid #ECECEC; +} .sale-data-table{ width: 100%; table-layout: fixed; @@ -242,6 +222,63 @@ } } +.sale-detail-toggle-wrap{ + border-top: 1px solid #ECECEC; +} +.sale-detail-toggle-bx{ + border-bottom: 1px solid #ECECEC; +} +.sale-detail-toggle-head{ + @include flex(5px); + padding: 14px 18px; + background-color: $white-fff; + cursor: pointer; + .sale-detail-toggle-name{ + @include defaultFont($font-s-13, $font-w-500, $font-c); + } + .sale-detail-toggle-btn-wrap{ + margin-left: auto; + .sale-detail-toggle-btn{ + display: block; + width: 22px; + height: 22px; + background: url(/assets/images/sub/sale_toggle_btn.svg)no-repeat center; + background-size: cover + } + } +} +.sale-detail-toggle-cont{ + display: none; + .sale-frame{ + padding: 24px 20px; + &:first-child{ + padding-top: 24px; + } + &:last-child{ + padding-bottom: 24px; + } + } +} + +.sale-detail-toggle-bx{ + &.act{ + .sale-detail-toggle-head{ + background-color: #5F738E; + .sale-detail-toggle-name{ + color: #fff + } + .sale-detail-toggle-btn-wrap{ + .sale-detail-toggle-btn{ + background: url(/assets/images/sub/sale_toggle_btn_white.svg)no-repeat center; + } + } + } + .sale-detail-toggle-cont{ + display: block; + } + } +} + // 매물 기본정보 .form-flex{ @include flex(5px); @@ -614,7 +651,14 @@ @include flex(0px); align-items: center; } - +.float-btn-wrap{ + position: sticky; + bottom: 10px; + left: 0; + width: 100%; + background-color: #fff; + z-index: 9; +} @media screen and (max-width: 360px){ .btn-flex-wrap{ flex-direction: column; diff --git a/src/styles/layout/_layout.scss b/src/styles/layout/_layout.scss index 95ae2e4..0389b2e 100644 --- a/src/styles/layout/_layout.scss +++ b/src/styles/layout/_layout.scss @@ -6,7 +6,7 @@ flex-direction: column; width: 100%; min-height: 100vh; - overflow-x: hidden; + // overflow-x: hidden; .container{ flex: 1 1 auto; } diff --git a/src/types/Survey.ts b/src/types/Survey.ts new file mode 100644 index 0000000..1401c47 --- /dev/null +++ b/src/types/Survey.ts @@ -0,0 +1,132 @@ +import { SEARCH_OPTIONS_ENUM, SEARCH_OPTIONS_PARTNERS_ENUM, SORT_OPTIONS_ENUM } from '@/store/surveyFilterStore' + +export type SurveyBasicInfo = { + ID: number + REPRESENTATIVE: string + STORE: string | null + CONSTRUCTION_POINT: string | null + INVESTIGATION_DATE: string | null + BUILDING_NAME: string | null + CUSTOMER_NAME: string | null + POST_CODE: string | null + ADDRESS: string | null + ADDRESS_DETAIL: string | null + SUBMISSION_STATUS: boolean + SUBMISSION_DATE: string | null + DETAIL_INFO: SurveyDetailInfo | null + REG_DT: Date + UPT_DT: Date +} + +export type SurveyDetailInfo = { + ID: number + BASIC_INFO_ID: number + CONTRACT_CAPACITY: string | null + RETAIL_COMPANY: string | null + SUPPLEMENTARY_FACILITIES: string | null // number 배열 + SUPPLEMENTARY_FACILITIES_ETC: string | null + INSTALLATION_SYSTEM: string | null + INSTALLATION_SYSTEM_ETC: string | null + CONSTRUCTION_YEAR: string | null + CONSTRUCTION_YEAR_ETC: string | null + ROOF_MATERIAL: string | null // number 배열 + ROOF_MATERIAL_ETC: string | null + ROOF_SHAPE: string | null + ROOF_SHAPE_ETC: string | null + ROOF_SLOPE: string | null + HOUSE_STRUCTURE: string | null + HOUSE_STRUCTURE_ETC: string | null + RAFTER_MATERIAL: string | null + RAFTER_MATERIAL_ETC: string | null + RAFTER_SIZE: string | null + RAFTER_SIZE_ETC: string | null + RAFTER_PITCH: string | null + RAFTER_PITCH_ETC: string | null + RAFTER_DIRECTION: string | null + OPEN_FIELD_PLATE_KIND: string | null + OPEN_FIELD_PLATE_KIND_ETC: string | null + OPEN_FIELD_PLATE_THICKNESS: string | null + LEAK_TRACE: boolean | null + WATERPROOF_MATERIAL: string | null + WATERPROOF_MATERIAL_ETC: string | null + INSULATION_PRESENCE: string | null + INSULATION_PRESENCE_ETC: string | null + STRUCTURE_ORDER: string | null + STRUCTURE_ORDER_ETC: string | null + INSTALLATION_AVAILABILITY: string | null + INSTALLATION_AVAILABILITY_ETC: string | null + MEMO: string | null + REG_DT: Date + UPT_DT: Date +} + +export type SurveyBasicRequest = { + REPRESENTATIVE: string + STORE: string | null + CONSTRUCTION_POINT: string | null + INVESTIGATION_DATE: string | null + BUILDING_NAME: string | null + CUSTOMER_NAME: string | null + POST_CODE: string | null + ADDRESS: string | null + ADDRESS_DETAIL: string | null + SUBMISSION_STATUS: boolean + SUBMISSION_DATE: string | null +} + +export type SurveyDetailRequest = { + CONTRACT_CAPACITY: string | null + RETAIL_COMPANY: string | null + SUPPLEMENTARY_FACILITIES: string | null // number 배열 + SUPPLEMENTARY_FACILITIES_ETC: string | null + INSTALLATION_SYSTEM: string | null + INSTALLATION_SYSTEM_ETC: string | null + CONSTRUCTION_YEAR: string | null + CONSTRUCTION_YEAR_ETC: string | null + ROOF_MATERIAL: string | null // number 배열 + ROOF_MATERIAL_ETC: string | null + ROOF_SHAPE: string | null + ROOF_SHAPE_ETC: string | null + ROOF_SLOPE: string | null + HOUSE_STRUCTURE: string | null + HOUSE_STRUCTURE_ETC: string | null + RAFTER_MATERIAL: string | null + RAFTER_MATERIAL_ETC: string | null + RAFTER_SIZE: string | null + RAFTER_SIZE_ETC: string | null + RAFTER_PITCH: string | null + RAFTER_PITCH_ETC: string | null + RAFTER_DIRECTION: string | null + OPEN_FIELD_PLATE_KIND: string | null + OPEN_FIELD_PLATE_KIND_ETC: string | null + OPEN_FIELD_PLATE_THICKNESS: string | null + LEAK_TRACE: boolean | null + WATERPROOF_MATERIAL: string | null + WATERPROOF_MATERIAL_ETC: string | null + INSULATION_PRESENCE: string | null + INSULATION_PRESENCE_ETC: string | null + STRUCTURE_ORDER: string | null + STRUCTURE_ORDER_ETC: string | null + INSTALLATION_AVAILABILITY: string | null + INSTALLATION_AVAILABILITY_ETC: string | null + MEMO: string | null +} + +export type SurveyDetailCoverRequest = { + DETAIL_INFO: SurveyDetailRequest +} + +export type SurveyRegistRequest = { + REPRESENTATIVE: string + STORE: string | null + CONSTRUCTION_POINT: string | null + INVESTIGATION_DATE: string | null + BUILDING_NAME: string | null + CUSTOMER_NAME: string | null + POST_CODE: string | null + ADDRESS: string | null + ADDRESS_DETAIL: string | null + SUBMISSION_STATUS: boolean + SUBMISSION_DATE: string | null + DETAIL_INFO: SurveyDetailRequest | null +}