Files
sam-manage/resources/views/barobill/settings/index.blade.php

781 lines
44 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@extends('layouts.app')
@section('title', '바로빌 연동 관리')
@section('content')
<!-- 현재 테넌트 정보 카드 -->
<x-barobill-tenant-header
:currentTenant="$currentTenant"
:barobillMember="$barobillMember"
:isTestMode="$isTestMode"
gradientFrom="#4f46e5"
gradientTo="#7c3aed"
:icon="'<svg class=&quot;w-7 h-7&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; viewBox=&quot;0 0 24 24&quot;><path stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z&quot; /><path stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;M15 12a3 3 0 11-6 0 3 3 0 016 0z&quot; /></svg>'"
/>
<!-- 서버 모드 제어 위젯 -->
@if($barobillMember)
<div class="bg-white rounded-lg shadow-sm p-6 mb-6">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 bg-gray-100 rounded-lg flex items-center justify-center">
<svg class="w-5 h-5 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01" />
</svg>
</div>
<div>
<h3 class="font-semibold text-gray-800">바로빌 서버 모드</h3>
<p class="text-xs text-gray-500">현재 바로빌 API 연결 서버 설정</p>
</div>
</div>
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<span class="text-sm text-gray-600">현재:</span>
@if($isTestMode)
<span id="server-mode-badge" class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-sm font-semibold bg-amber-100 text-amber-800">
<span class="w-2 h-2 rounded-full bg-amber-500"></span>
테스트 서버
</span>
@else
<span id="server-mode-badge" class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-sm font-semibold bg-green-100 text-green-800">
<span class="w-2 h-2 rounded-full bg-green-500"></span>
운영 서버
</span>
@endif
</div>
@if(session('selected_tenant_id', 1) == 1)
<button type="button" id="btn-toggle-server-mode" onclick="toggleServerMode()" class="inline-flex items-center gap-2 px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition text-sm font-medium">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
</svg>
서버 변경
</button>
@endif
</div>
@if($isTestMode)
<div class="mt-4 p-3 bg-amber-50 border border-amber-200 rounded-lg">
<div class="flex items-start gap-2">
<svg class="w-4 h-4 text-amber-600 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<p class="text-sm text-amber-700">테스트 서버 사용 중입니다. 테스트 데이터는 실제 국세청에 전송되지 않습니다.</p>
</div>
</div>
@else
<div class="mt-4 p-3 bg-green-50 border border-green-200 rounded-lg">
<div class="flex items-start gap-2">
<svg class="w-4 h-4 text-green-600 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<p class="text-sm text-green-700">운영 서버에 연결되어 있습니다. 모든 데이터가 실제 국세청에 전송됩니다.</p>
</div>
</div>
@endif
</div>
@endif
<!-- 바로빌 연동 -->
<div class="mb-6">
<h2 class="text-lg font-bold text-gray-800 mb-3">바로빌 연동</h2>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
<!-- 카드 1: 바로빌 로그인 정보 -->
<div class="bg-white rounded-lg shadow-sm p-6">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 bg-indigo-100 rounded-lg flex items-center justify-center">
<svg class="w-5 h-5 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
</svg>
</div>
<div>
<h3 class="font-semibold text-gray-800">바로빌 로그인 정보</h3>
<p class="text-xs text-gray-500">바로빌 회원 아이디/비밀번호 관리</p>
</div>
</div>
@if($hasBarobillLogin)
<div class="space-y-3">
<div class="flex items-center gap-2">
<span class="text-sm text-gray-500 shrink-0" style="width: 60px;">아이디</span>
<span class="text-sm font-medium text-gray-800">{{ $barobillMember->barobill_id }}</span>
</div>
<div class="flex items-center gap-2">
<span class="text-sm text-gray-500 shrink-0" style="width: 60px;">비밀번호</span>
<span class="text-sm font-medium text-gray-800">●●●●●●●●</span>
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">설정됨</span>
</div>
<button type="button" onclick="openBarobillLoginModal('edit')"
class="mt-2 w-full px-4 py-2 bg-indigo-50 text-indigo-700 rounded-lg hover:bg-indigo-100 transition text-sm font-medium flex items-center justify-center gap-2">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
</svg>
로그인 정보 수정
</button>
</div>
@else
<div class="text-center py-4">
<div class="w-12 h-12 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-3">
<svg class="w-6 h-6 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
</svg>
</div>
<h4 class="font-medium text-gray-800 mb-1">바로빌 회원이신가요?</h4>
<p class="text-sm text-gray-500 mb-4">바로빌 ID와 비밀번호를 등록하면<br>계좌/카드 연동 서비스를 이용할 있습니다.</p>
<button type="button" onclick="openBarobillLoginModal('register')"
class="w-full px-4 py-2.5 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition text-sm font-medium flex items-center justify-center gap-2">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
바로빌 로그인 정보 등록
</button>
</div>
@endif
</div>
<!-- 카드 2: 바로빌 회원가입 안내 -->
<div class="bg-white rounded-lg shadow-sm p-6">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 bg-blue-100 rounded-lg flex items-center justify-center">
<svg class="w-5 h-5 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18 9v3m0 0v3m0-3h3m-3 0h-3m-2-5a4 4 0 11-8 0 4 4 0 018 0zM3 20a6 6 0 0112 0v1H3v-1z" />
</svg>
</div>
<div>
<h3 class="font-semibold text-gray-800">바로빌 회원가입</h3>
<p class="text-xs text-gray-500">바로빌 서비스 신규 가입</p>
</div>
</div>
<div class="text-center py-4">
<div class="w-12 h-12 bg-blue-50 rounded-full flex items-center justify-center mx-auto mb-3">
<svg class="w-6 h-6 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<h4 class="font-medium text-gray-800 mb-1">바로빌 회원이 아니신가요?</h4>
<p class="text-sm text-gray-500 mb-4">바로빌 회원가입 <br>전자세금계산서, 계좌조회 등의 서비스를 이용하세요.</p>
<a href="https://www.barobill.co.kr" target="_blank" rel="noopener noreferrer"
class="inline-flex w-full px-4 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition text-sm font-medium items-center justify-center gap-2">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
바로빌 회원가입
</a>
</div>
</div>
</div>
</div>
<!-- 계좌 연동 -->
<div class="mb-6">
<h2 class="text-lg font-bold text-gray-800 mb-3">계좌 연동</h2>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
<!-- 은행 빠른조회 서비스 등록 -->
<div class="bg-white rounded-lg shadow-sm p-6 {{ !$hasBarobillLogin ? 'opacity-50' : '' }}">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 bg-green-100 rounded-lg flex items-center justify-center">
<svg class="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" />
</svg>
</div>
<div>
<h3 class="font-semibold text-gray-800">은행 빠른조회 서비스</h3>
<p class="text-xs text-gray-500">은행 계좌 빠른조회 서비스 등록</p>
</div>
</div>
@if($hasBarobillLogin)
<button type="button" onclick="openBarobillUrl('bank-account-url')"
class="w-full px-4 py-2 bg-green-50 text-green-700 rounded-lg hover:bg-green-100 transition text-sm font-medium flex items-center justify-center gap-2">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
서비스 등록하기
</button>
@else
<p class="text-sm text-gray-400 text-center py-2">바로빌 로그인 정보를 먼저 등록하세요.</p>
@endif
</div>
<!-- 계좌 연동 등록 -->
<div class="bg-white rounded-lg shadow-sm p-6 {{ !$hasBarobillLogin ? 'opacity-50' : '' }}">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 bg-green-100 rounded-lg flex items-center justify-center">
<svg class="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div>
<h3 class="font-semibold text-gray-800">계좌 연동 관리</h3>
<p class="text-xs text-gray-500">은행 계좌 연동 등록 관리</p>
</div>
</div>
@if($hasBarobillLogin)
<button type="button" onclick="openBarobillUrl('bank-account-manage-url')"
class="w-full px-4 py-2 bg-green-50 text-green-700 rounded-lg hover:bg-green-100 transition text-sm font-medium flex items-center justify-center gap-2">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
계좌 관리하기
</button>
@else
<p class="text-sm text-gray-400 text-center py-2">바로빌 로그인 정보를 먼저 등록하세요.</p>
@endif
</div>
</div>
</div>
<!-- 카드 연동 -->
<div class="mb-6">
<h2 class="text-lg font-bold text-gray-800 mb-3">카드 연동</h2>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
<!-- 카드 연동 등록 -->
<div class="bg-white rounded-lg shadow-sm p-6 {{ !$hasBarobillLogin ? 'opacity-50' : '' }}">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 bg-purple-100 rounded-lg flex items-center justify-center">
<svg class="w-5 h-5 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" />
</svg>
</div>
<div>
<h3 class="font-semibold text-gray-800">카드 연동 관리</h3>
<p class="text-xs text-gray-500">카드 연동 등록 관리</p>
</div>
</div>
@if($hasBarobillLogin)
<button type="button" onclick="openBarobillUrl('card-url')"
class="w-full px-4 py-2 bg-purple-50 text-purple-700 rounded-lg hover:bg-purple-100 transition text-sm font-medium flex items-center justify-center gap-2">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
카드 관리하기
</button>
@else
<p class="text-sm text-gray-400 text-center py-2">바로빌 로그인 정보를 먼저 등록하세요.</p>
@endif
</div>
<!-- 공인인증서 등록 -->
<div class="bg-white rounded-lg shadow-sm p-6 {{ !$hasBarobillLogin ? 'opacity-50' : '' }}">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 bg-amber-100 rounded-lg flex items-center justify-center">
<svg class="w-5 h-5 text-amber-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
</svg>
</div>
<div>
<h3 class="font-semibold text-gray-800">공인인증서 등록</h3>
<p class="text-xs text-gray-500">공인인증서 등록 관리</p>
</div>
</div>
@if($hasBarobillLogin)
<button type="button" onclick="openBarobillUrl('certificate-url')"
class="w-full px-4 py-2 bg-amber-50 text-amber-700 rounded-lg hover:bg-amber-100 transition text-sm font-medium flex items-center justify-center gap-2">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
인증서 관리하기
</button>
@else
<p class="text-sm text-gray-400 text-center py-2">바로빌 로그인 정보를 먼저 등록하세요.</p>
@endif
</div>
</div>
</div>
<div class="flex flex-col h-full">
<!-- 페이지 헤더 -->
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4 mb-6 flex-shrink-0">
<div>
<h1 class="text-2xl font-bold text-gray-800">바로빌 설정</h1>
<p class="text-sm text-gray-500 mt-1">이메일 주소 기타 자료의 수정 동기화</p>
</div>
</div>
<!-- 설정 카드 -->
<form id="settings-form" class="space-y-6">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- 서비스 이용 설정 -->
<div class="bg-white rounded-lg shadow-sm p-6 lg:col-span-2">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 bg-indigo-100 rounded-lg flex items-center justify-center">
<svg class="w-5 h-5 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div>
<h3 class="font-semibold text-gray-800">서비스 이용 설정</h3>
<p class="text-xs text-gray-500">이용할 바로빌 서비스를 선택하세요</p>
</div>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
<!-- 전자세금계산서 -->
<label class="flex items-start gap-3 p-4 bg-gray-50 rounded-lg cursor-pointer hover:bg-gray-100 transition border-2 border-transparent has-[:checked]:border-blue-500 has-[:checked]:bg-blue-50">
<input type="checkbox" name="use_tax_invoice" id="use_tax_invoice" class="service-checkbox mt-1 w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500" onchange="saveServiceSetting('use_tax_invoice', this.checked)">
<div>
<div class="flex items-center gap-2">
<svg class="w-5 h-5 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<span class="font-medium text-gray-800">전자세금계산서</span>
</div>
<p class="text-xs text-gray-500 mt-1">세금계산서 발행/수신 서비스</p>
</div>
</label>
<!-- 계좌조회 -->
<label class="flex items-start gap-3 p-4 bg-gray-50 rounded-lg cursor-pointer hover:bg-gray-100 transition border-2 border-transparent has-[:checked]:border-green-500 has-[:checked]:bg-green-50">
<input type="checkbox" name="use_bank_account" id="use_bank_account" class="service-checkbox mt-1 w-4 h-4 text-green-600 bg-gray-100 border-gray-300 rounded focus:ring-green-500" onchange="saveServiceSetting('use_bank_account', this.checked)">
<div>
<div class="flex items-center gap-2">
<svg class="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" />
</svg>
<span class="font-medium text-gray-800">계좌조회</span>
</div>
<p class="text-xs text-gray-500 mt-1">은행 계좌 거래내역 조회</p>
</div>
</label>
<!-- 카드사용내역 -->
<label class="flex items-start gap-3 p-4 bg-gray-50 rounded-lg cursor-pointer hover:bg-gray-100 transition border-2 border-transparent has-[:checked]:border-purple-500 has-[:checked]:bg-purple-50">
<input type="checkbox" name="use_card_usage" id="use_card_usage" class="service-checkbox mt-1 w-4 h-4 text-purple-600 bg-gray-100 border-gray-300 rounded focus:ring-purple-500" onchange="saveServiceSetting('use_card_usage', this.checked)">
<div>
<div class="flex items-center gap-2">
<svg class="w-5 h-5 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" />
</svg>
<span class="font-medium text-gray-800">카드사용내역</span>
</div>
<p class="text-xs text-gray-500 mt-1">카드 결제내역 조회</p>
</div>
</label>
<!-- 홈텍스매입/매출 -->
<label class="flex items-start gap-3 p-4 bg-gray-50 rounded-lg cursor-pointer hover:bg-gray-100 transition border-2 border-transparent has-[:checked]:border-orange-500 has-[:checked]:bg-orange-50">
<input type="checkbox" name="use_hometax" id="use_hometax" class="service-checkbox mt-1 w-4 h-4 text-orange-600 bg-gray-100 border-gray-300 rounded focus:ring-orange-500" onchange="saveServiceSetting('use_hometax', this.checked)">
<div>
<div class="flex items-center gap-2">
<svg class="w-5 h-5 text-orange-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 7h6m0 10v-3m-3 3h.01M9 17h.01M9 14h.01M12 14h.01M15 11h.01M12 11h.01M9 11h.01M7 21h10a2 2 0 002-2V5a2 2 0 00-2-2H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
</svg>
<span class="font-medium text-gray-800">홈텍스매입/매출</span>
</div>
<p class="text-xs text-gray-500 mt-1">홈텍스 매입/매출 자료 조회</p>
</div>
</label>
</div>
</div>
<!-- 담당자 정보 -->
<div class="bg-white rounded-lg shadow-sm p-6">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 bg-blue-100 rounded-lg flex items-center justify-center">
<svg class="w-5 h-5 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
</svg>
</div>
<div>
<h3 class="font-semibold text-gray-800">담당자 정보</h3>
<p class="text-xs text-gray-500">세금계산서 담당자 정보</p>
</div>
</div>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-600 mb-1">담당자명</label>
<input type="text" name="contact_name" id="contact_name" class="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="홍길동">
</div>
<div>
<label class="block text-sm font-medium text-gray-600 mb-1">연락처</label>
<input type="tel" name="contact_tel" id="contact_tel" class="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="02-1234-5678">
</div>
<div>
<label class="block text-sm font-medium text-gray-600 mb-1">담당자 이메일</label>
<input type="email" name="contact_id" id="contact_id" class="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="manager@company.com">
</div>
</div>
</div>
<!-- 동기화 설정 -->
<div class="bg-white rounded-lg shadow-sm p-6">
<div class="flex items-center gap-3 mb-4">
<div class="w-10 h-10 bg-green-100 rounded-lg flex items-center justify-center">
<svg class="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
</div>
<div>
<h3 class="font-semibold text-gray-800">데이터 동기화</h3>
<p class="text-xs text-gray-500">바로빌 데이터 동기화 설정</p>
</div>
</div>
<div class="space-y-4">
<div class="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
<div>
<p class="text-sm font-medium text-gray-700">자동 동기화</p>
<p class="text-xs text-gray-500">매일 자정 자동 동기화</p>
</div>
<label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" class="sr-only peer">
<div class="w-11 h-6 bg-gray-200 peer-focus:ring-2 peer-focus:ring-blue-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600"></div>
</label>
</div>
<button type="button" class="w-full px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition flex items-center justify-center gap-2">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
</svg>
지금 동기화
</button>
</div>
</div>
</div>
<!-- 저장 버튼 -->
<div class="flex justify-end gap-3">
<button type="button" id="btn-reset" class="px-6 py-2.5 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition font-medium">
초기화
</button>
<button type="submit" id="btn-save" class="px-6 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition font-medium flex items-center gap-2">
<svg class="w-4 h-4 hidden animate-spin" id="save-spinner" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
설정 저장
</button>
</div>
</form>
<!-- 토스트 메시지 -->
<div id="toast" class="fixed bottom-4 right-4 px-4 py-3 rounded-lg shadow-lg transform translate-y-full opacity-0 transition-all duration-300 z-50"></div>
</div>
<!-- 바로빌 로그인 정보 등록/수정 모달 -->
<div id="barobill-login-modal" class="fixed inset-0 z-50 hidden">
<div class="fixed inset-0 bg-black/50" onclick="closeBarobillLoginModal()"></div>
<div class="fixed inset-0 flex items-center justify-center p-4">
<div class="bg-white rounded-xl shadow-2xl w-full max-w-md relative">
<div class="flex items-center justify-between p-6 border-b border-gray-100">
<h3 id="barobill-login-modal-title" class="text-lg font-bold text-gray-800">바로빌 로그인 정보</h3>
<button type="button" onclick="closeBarobillLoginModal()" class="text-gray-400 hover:text-gray-600">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div class="p-6 space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">바로빌 아이디</label>
<input type="text" id="modal-barobill-id" class="w-full px-3 py-2.5 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="바로빌 아이디를 입력하세요">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">바로빌 비밀번호</label>
<input type="password" id="modal-barobill-pwd" class="w-full px-3 py-2.5 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="비밀번호를 입력하세요">
</div>
</div>
<div class="flex gap-3 p-6 border-t border-gray-100">
<button type="button" onclick="closeBarobillLoginModal()" class="flex-1 px-4 py-2.5 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition text-sm font-medium">취소</button>
<button type="button" id="btn-save-barobill-login" onclick="saveBarobillLogin()" class="flex-1 px-4 py-2.5 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition text-sm font-medium flex items-center justify-center gap-2">
<svg class="w-4 h-4 hidden animate-spin" id="barobill-login-spinner" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" fill="none"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
저장
</button>
</div>
</div>
</div>
</div>
@endsection
@push('scripts')
<script>
// 바로빌 로그인 모달
function openBarobillLoginModal(mode) {
const modal = document.getElementById('barobill-login-modal');
const title = document.getElementById('barobill-login-modal-title');
const idInput = document.getElementById('modal-barobill-id');
const pwdInput = document.getElementById('modal-barobill-pwd');
if (mode === 'edit') {
title.textContent = '바로빌 로그인 정보 수정';
idInput.value = @json($barobillMember?->barobill_id ?? '');
pwdInput.value = '';
pwdInput.placeholder = '변경할 비밀번호를 입력하세요 (미입력 시 유지)';
} else {
title.textContent = '바로빌 로그인 정보 등록';
idInput.value = '';
pwdInput.value = '';
pwdInput.placeholder = '비밀번호를 입력하세요';
}
modal.classList.remove('hidden');
}
function closeBarobillLoginModal() {
document.getElementById('barobill-login-modal').classList.add('hidden');
}
async function saveBarobillLogin() {
const memberId = @json($barobillMember?->id);
if (!memberId) {
showToast('바로빌 회원사 정보가 없습니다.', 'error');
return;
}
const barobillId = document.getElementById('modal-barobill-id').value.trim();
const barobillPwd = document.getElementById('modal-barobill-pwd').value;
if (!barobillId) {
showToast('바로빌 아이디를 입력하세요.', 'error');
return;
}
const spinner = document.getElementById('barobill-login-spinner');
const btn = document.getElementById('btn-save-barobill-login');
spinner.classList.remove('hidden');
btn.disabled = true;
try {
const body = { barobill_id: barobillId };
if (barobillPwd) {
body.barobill_pwd = barobillPwd;
}
const response = await fetch(`/api/admin/barobill/members/${memberId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
},
body: JSON.stringify(body),
});
const result = await response.json();
if (result.success) {
showToast('바로빌 로그인 정보가 저장되었습니다.', 'success');
closeBarobillLoginModal();
setTimeout(() => location.reload(), 1000);
} else {
showToast(result.message || '저장에 실패했습니다.', 'error');
}
} catch (error) {
console.error('바로빌 로그인 정보 저장 실패:', error);
showToast('저장 중 오류가 발생했습니다.', 'error');
} finally {
spinner.classList.add('hidden');
btn.disabled = false;
}
}
// 바로빌 URL API 호출 (계좌/카드/인증서)
async function openBarobillUrl(urlType) {
const memberId = @json($barobillMember?->id);
if (!memberId) {
showToast('바로빌 회원사 정보가 없습니다.', 'error');
return;
}
try {
const response = await fetch(`/api/admin/barobill/members/${memberId}/${urlType}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
},
});
const result = await response.json();
if (result.success && result.data?.url) {
window.open(result.data.url, '_blank', 'width=900,height=700');
} else {
showToast(result.message || 'URL을 가져오는데 실패했습니다.', 'error');
}
} catch (error) {
console.error('바로빌 URL 호출 실패:', error);
showToast('서비스 연결 중 오류가 발생했습니다.', 'error');
}
}
// 서버 모드 전환
async function toggleServerMode() {
const isCurrentlyTest = @json($isTestMode);
const targetMode = isCurrentlyTest ? 'production' : 'test';
const targetLabel = isCurrentlyTest ? '운영' : '테스트';
let confirmMessage = `서버를 "${targetLabel}" 모드로 변경하시겠습니까?`;
if (targetMode === 'production') {
confirmMessage += '\n\n⚠ 운영 서버로 전환하면 실제 요금이 부과되며, 발행된 세금계산서가 국세청에 전송됩니다.';
}
if (!confirm(confirmMessage)) return;
const memberId = @json($barobillMember?->id);
if (!memberId) {
showToast('바로빌 회원사 정보가 없습니다.', 'error');
return;
}
try {
const response = await fetch(`/api/admin/barobill/members/${memberId}/server-mode`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
},
body: JSON.stringify({ server_mode: targetMode }),
});
const result = await response.json();
if (result.success) {
showToast(`서버 모드가 "${targetLabel}"(으)로 변경되었습니다.`, 'success');
setTimeout(() => location.reload(), 1000);
} else {
showToast(result.message || '서버 모드 변경에 실패했습니다.', 'error');
}
} catch (error) {
console.error('서버 모드 변경 실패:', error);
showToast('서버 모드 변경 중 오류가 발생했습니다.', 'error');
}
}
// 서비스 설정 개별 저장 (체크박스 변경 시 즉시 저장)
async function saveServiceSetting(field, value) {
const toast = document.getElementById('toast');
try {
const response = await fetch('/api/admin/barobill/settings/service', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
},
body: JSON.stringify({ field: field, value: value }),
});
const result = await response.json();
if (result.success) {
showToast(result.message || '설정이 저장되었습니다.', 'success');
} else {
showToast(result.message || '설정 저장에 실패했습니다.', 'error');
// 실패 시 체크박스 원상복구
document.getElementById(field).checked = !value;
}
} catch (error) {
console.error('설정 저장 실패:', error);
showToast('설정 저장 중 오류가 발생했습니다.', 'error');
// 실패 시 체크박스 원상복구
document.getElementById(field).checked = !value;
}
}
// 토스트 표시 (전역 함수)
function showToast(message, type = 'success') {
const toast = document.getElementById('toast');
toast.textContent = message;
toast.className = 'fixed bottom-4 right-4 px-4 py-3 rounded-lg shadow-lg transform transition-all duration-300 z-50';
if (type === 'success') {
toast.classList.add('bg-green-600', 'text-white');
} else {
toast.classList.add('bg-red-600', 'text-white');
}
toast.classList.remove('translate-y-full', 'opacity-0');
setTimeout(() => {
toast.classList.add('translate-y-full', 'opacity-0');
}, 3000);
}
document.addEventListener('DOMContentLoaded', function() {
const form = document.getElementById('settings-form');
const saveSpinner = document.getElementById('save-spinner');
const btnSave = document.getElementById('btn-save');
const btnReset = document.getElementById('btn-reset');
// 설정 로드
async function loadSettings() {
try {
const response = await fetch('/api/admin/barobill/settings');
const result = await response.json();
if (result.success && result.data) {
const data = result.data;
// 서비스 이용 설정
document.getElementById('use_tax_invoice').checked = data.use_tax_invoice || false;
document.getElementById('use_bank_account').checked = data.use_bank_account || false;
document.getElementById('use_card_usage').checked = data.use_card_usage || false;
document.getElementById('use_hometax').checked = data.use_hometax || false;
// 담당자 정보
document.getElementById('contact_name').value = data.contact_name || '';
document.getElementById('contact_tel').value = data.contact_tel || '';
document.getElementById('contact_id').value = data.contact_id || '';
}
} catch (error) {
console.error('설정 로드 실패:', error);
}
}
// 설정 저장
async function saveSettings(e) {
e.preventDefault();
saveSpinner.classList.remove('hidden');
btnSave.disabled = true;
const formData = {
use_tax_invoice: document.getElementById('use_tax_invoice').checked,
use_bank_account: document.getElementById('use_bank_account').checked,
use_card_usage: document.getElementById('use_card_usage').checked,
use_hometax: document.getElementById('use_hometax').checked,
contact_name: document.getElementById('contact_name').value,
contact_tel: document.getElementById('contact_tel').value,
contact_id: document.getElementById('contact_id').value,
};
try {
const response = await fetch('/api/admin/barobill/settings', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
},
body: JSON.stringify(formData),
});
const result = await response.json();
if (result.success) {
showToast(result.message || '설정이 저장되었습니다.', 'success');
} else {
showToast(result.message || '설정 저장에 실패했습니다.', 'error');
}
} catch (error) {
console.error('설정 저장 실패:', error);
showToast('설정 저장 중 오류가 발생했습니다.', 'error');
} finally {
saveSpinner.classList.add('hidden');
btnSave.disabled = false;
}
}
// 초기화 버튼
btnReset.addEventListener('click', function() {
document.getElementById('use_tax_invoice').checked = false;
document.getElementById('use_bank_account').checked = false;
document.getElementById('use_card_usage').checked = false;
document.getElementById('use_hometax').checked = false;
document.getElementById('contact_name').value = '';
document.getElementById('contact_tel').value = '';
document.getElementById('contact_id').value = '';
showToast('설정이 초기화되었습니다.', 'success');
});
// 이벤트 리스너
form.addEventListener('submit', saveSettings);
// 초기 로드
loadSettings();
});
</script>
@endpush