[예시] 주문 데이터 조회 및 티켓 관리

menus:
  - name: 주문 기반 티켓 관리
    path: support0122

pages:
  - path: support0122
    title: 주문 / 티켓 관리

    resetButton:
      label: 초기화
      type: light

    params:
      - key: order_id
        label: 주문번호
        type: text
        placeholder: "예) O-1001"

      - key: customer_name
        label: 고객명
        type: text
        placeholder: "예) 김민수"

      - key: order_status
        label: 주문상태
        defaultValue: ""
        radioButtonGroup: true
        radio:
          - label: 전체
            value: ""
          - label: 결제완료
            value: paid
          - label: 배송중
            value: shipped
          - label: 배송완료
            value: delivered

      - key: ticket_status
        label: 티켓상태
        defaultValue: ""
        radioButtonGroup: true
        radio:
          - label: 전체
            value: ""
          - label: 오픈
            value: open
          - label: 보류
            value: pending
          - label: 해결
            value: resolved

      - key: ticket_type
        label: 티켓유형
        type: select
        dropdown:
          - label: 전체
            value: ""
          - label: 파손
            value: 파손
          - label: 환불
            value: 환불
          - label: 배송
            value: 배송

      - key: assignee
        label: 담당자
        type: select
        dropdown:
          - label: 전체
            value: ""
          - label: 물류팀
            value: 물류팀
          - label: CS팀
            value: CS팀

    blocks:
      - type: top
        blocks:
          - type: query
            name: 상단 요약
            resource: mysql.sample
            sqlType: select
            display: metric
            width: 500px
            showDownload: false
            sql: |
              SELECT
                (
                  SELECT COUNT(*)
                  FROM (
                    SELECT 'O-1001' AS order_id, '김민수' AS customer_name, 'shipped' AS status, 32000 AS amount
                    UNION ALL
                    SELECT 'O-1002', '이영희', 'paid', 15000
                    UNION ALL
                    SELECT 'O-1003', '박지훈', 'delivered', 54000
                  ) orders
                  WHERE 1=1
                    AND (:order_id IS NULL OR :order_id = '' OR orders.order_id LIKE CONCAT('%', :order_id, '%'))
                    AND (:customer_name IS NULL OR :customer_name = '' OR orders.customer_name LIKE CONCAT('%', :customer_name, '%'))
                    AND (:order_status IS NULL OR :order_status = '' OR orders.status = :order_status)
                ) AS total_orders,

                (
                  SELECT COUNT(*)
                  FROM (
                    SELECT 'T-1' AS ticket_id, 'O-1001' AS order_id, '파손' AS type, 'open' AS status, '물류팀' AS assignee
                    UNION ALL
                    SELECT 'T-2', 'O-1001', '환불', 'resolved', 'CS팀'
                    UNION ALL
                    SELECT 'T-3', 'O-1002', '배송', 'pending', 'CS팀'
                  ) tickets
                  WHERE 1=1
                    AND tickets.status IN ('open','pending')
                    AND (:order_id IS NULL OR :order_id = '' OR tickets.order_id LIKE CONCAT('%', :order_id, '%'))
                    AND (:ticket_status IS NULL OR :ticket_status = '' OR tickets.status = :ticket_status)
                    AND (:ticket_type IS NULL OR :ticket_type = '' OR tickets.type = :ticket_type)
                    AND (:assignee IS NULL OR :assignee = '' OR tickets.assignee = :assignee)
                ) AS open_tickets,

                (
                  SELECT COALESCE(SUM(orders.amount), 0)
                  FROM (
                    SELECT 'O-1001' AS order_id, '김민수' AS customer_name, 'shipped' AS status, 32000 AS amount
                    UNION ALL
                    SELECT 'O-1002', '이영희', 'paid', 15000
                    UNION ALL
                    SELECT 'O-1003', '박지훈', 'delivered', 54000
                  ) orders
                  WHERE 1=1
                    AND (:order_id IS NULL OR :order_id = '' OR orders.order_id LIKE CONCAT('%', :order_id, '%'))
                    AND (:customer_name IS NULL OR :customer_name = '' OR orders.customer_name LIKE CONCAT('%', :customer_name, '%'))
                    AND (:order_status IS NULL OR :order_status = '' OR orders.status = :order_status)
                ) AS total_amount
            columns:
              total_orders:
                label: 전체 주문
                type: number
                formatFn: number0
              open_tickets:
                label: 미해결 티켓
                type: number
                formatFn: number0
              total_amount:
                label: 주문 합계(원)
                type: number
                formatFn:
                  - number0
                  - ""
                  - " 원"

      - type: left
        blocks:
          - type: query
            name: 주문 내역
            resource: mysql.sample
            sqlType: select
            showDownload: false
            sql: |
              SELECT *
              FROM (
                SELECT 'O-1001' AS order_id, '김민수' AS customer_name, 'shipped' AS status, 32000 AS amount
                UNION ALL
                SELECT 'O-1002', '이영희', 'paid', 15000
                UNION ALL
                SELECT 'O-1003', '박지훈', 'delivered', 54000
              ) orders
              WHERE 1=1
                AND (:order_id IS NULL OR :order_id = '' OR orders.order_id LIKE CONCAT('%', :order_id, '%'))
                AND (:customer_name IS NULL OR :customer_name = '' OR orders.customer_name LIKE CONCAT('%', :customer_name, '%'))
                AND (:order_status IS NULL OR :order_status = '' OR orders.status = :order_status)
              ORDER BY orders.order_id DESC
            columns:
              order_id:
                label: 주문번호
                width: 140px
                copy: true
                subtitle: customer_name
                updateParams:
                  order_id: "{{order_id}}"
              customer_name:
                label: 고객명
                hidden: true
              status:
                label: 상태
                width: 120px
                valueAs:
                  paid: 결제완료
                  shipped: 배송중
                  delivered: 배송완료
                color:
                  paid: green
                  shipped: blue
                  delivered: gray
              amount:
                label: 금액
                type: number
                width: 140px
                formatFn:
                  - number0
                  - ""
                  - " 원"
              ' ':
                append: true                
                buttons:
                  - label: + 티켓
                    openModal: order-:order_id-new-ticket
            modals:
              - path: order-:order_id-new-ticket
                header: false
                name: 새 티켓
                blocks:
                  - type: query
                    name: 티켓 생성
                    resource: mysql.sample
                    sqlType: insert
                    display: form
                    formOptions:
                      firstLabelWidth: 120px
                    showDownload: false
                    closeAfterSubmit: true
                    sql: |
                      SELECT 1
                    params:
                      - key: order_id
                        hidden: true
                        valueFromRow: true
                      - key: type
                        label: 티켓유형
                        defaultValue: 파손
                        dropdown:
                          - label: 파손
                            value: 파손
                          - label: 환불
                            value: 환불
                          - label: 배송
                            value: 배송
                      - key: status
                        label: 상태
                        defaultValue: open
                        radioButtonGroup: true
                        radio:
                          - label: 오픈
                            value: open
                          - label: 보류
                            value: pending
                          - label: 해결
                            value: resolved
                      - key: priority
                        label: 우선순위
                        defaultValue: medium
                        radioButtonGroup: true
                        radio:
                          - label: 높음
                            value: high
                          - label: 보통
                            value: medium
                          - label: 낮음
                            value: low
                      - key: assignee
                        label: 담당자
                        defaultValue: CS팀
                        dropdown:
                          - label: 물류팀
                            value: 물류팀
                          - label: CS팀
                            value: CS팀
                      - key: memo
                        label: 내부 메모
                        format: textarea
                        rows: 3
                        placeholder: "예) 고객이 파손 사진을 전달함 / 배송 지연 확인 필요"
                        required: false
                      - key: email
                        valueFromUserProperty: "{{email}}"
                        hidden: true

      - type: right
        style:
          width: 700px
        blocks:
          - type: query
            name: 티켓 목록
            resource: mysql.sample
            sqlType: select
            showDownload: false
            sql: |
              SELECT *
              FROM (
                SELECT 'T-1' AS ticket_id, 'O-1001' AS order_id, '파손' AS type, 'open' AS status, '물류팀' AS assignee
                UNION ALL
                SELECT 'T-2', 'O-1001', '환불', 'resolved', 'CS팀'
                UNION ALL
                SELECT 'T-3', 'O-1002', '배송', 'pending', 'CS팀'
              ) tickets
              WHERE 1=1
                AND (:order_id IS NULL OR :order_id = '' OR tickets.order_id LIKE CONCAT('%', :order_id, '%'))
                AND (:ticket_status IS NULL OR :ticket_status = '' OR tickets.status = :ticket_status)
                AND (:ticket_type IS NULL OR :ticket_type = '' OR tickets.type = :ticket_type)
                AND (:assignee IS NULL OR :assignee = '' OR tickets.assignee = :assignee)
              ORDER BY tickets.ticket_id DESC
            columns:
              ticket_id:
                label: 티켓 ID
                width: 120px
                copy: true
                buttons:
                  - label: 상세
                    openModal: ticket-detail-:ticket_id
              order_id:
                label: 주문번호
                width: 140px
                copy: true
              type:
                label: 유형
                width: 100px
                color:
                  파손: orange
                  환불: purple
                  배송: blue
              status:
                label: 상태
                width: 110px
                valueAs:
                  open: 오픈
                  pending: 보류
                  resolved: 해결
                color:
                  open: red
                  pending: yellow
                  resolved: green
              assignee:
                label: 담당자
                width: 110px
                color:
                  물류팀: blue
                  CS팀: gray

            modals:
              - path: ticket-detail-:ticket_id
                name: 티켓 상세
                header: false
                height: 760px
                blocks:
                  - type: query
                    name: 티켓 상세 정보
                    resource: mysql.sample
                    sqlType: select
                    display: form
                    sql: |
                      SELECT *
                      FROM (
                        SELECT
                          'T-1' AS ticket_id,
                          'O-1001' AS order_id,
                          '파손' AS type,
                          'open' AS status,
                          'high' AS priority,
                          '물류팀' AS assignee,
                          '상품 파손 사진 수령' AS memo
                        UNION ALL
                        SELECT
                          'T-2',
                          'O-1001',
                          '환불',
                          'resolved',
                          'low',
                          'CS팀',
                          '환불 완료'
                        UNION ALL
                        SELECT
                          'T-3',
                          'O-1002',
                          '배송',
                          'pending',
                          'medium',
                          'CS팀',
                          '배송 지연 확인 중'
                      ) t
                      WHERE t.ticket_id = :ticket_id
                    params:
                      - key: ticket_id
                        valueFromRow: true
                    columns:
                      ticket_id:
                        label: 티켓 ID
                        copy: true
                      order_id:
                        label: 주문번호
                        copy: true
                      type:
                        label: 유형
                        color:
                          파손: orange
                          환불: purple
                          배송: blue
                      status:
                        label: 상태
                        valueAs:
                          open: 오픈
                          pending: 보류
                          resolved: 해결
                        color:
                          open: red
                          pending: yellow
                          resolved: green
                      priority:
                        label: 우선순위
                        valueAs:
                          high: 높음
                          medium: 보통
                          low: 낮음
                        color:
                          high: red
                          medium: orange
                          low: gray
                      assignee:
                        label: 담당자
                        color:
                          물류팀: blue
                          CS팀: gray
                      memo:
                        label: 내부 메모
                        updateOptions:
                          type: query
                          resource: mysql.sample
                          sqlType: update
                          sql: SELECT 1
                          params:
                            - key: ticket_id
                              hidden: true
                              valueFromRow: true
                            - key: memo
                              label: 내부 메모
                              type: textarea

                    actions:
                      - label: 삭제
                        type: query
                        resource: mysql.sample
                        sqlType: update
                        single: true
                        placement: right bottom
                        button:
                          type: danger-light
                        params:
                          - key: ticket_id
                            hidden: true
                            valueFromRow: true
                        sql: |
                          SELECT 1

                      - label: 상태 변경
                        single: true
                        placement: left bottom
                        openPopper: true
                        popperOptions:
                          placement: bottom
                        popperStyle:
                          width: 420px
                          padding: 16px
                        blocks:
                          - type: query
                            name: 티켓 상태 변경
                            resource: mysql.sample
                            sqlType: update
                            display: form
                            showDownload: false
                            closeAfterSubmit: true
                            params:
                              - key: ticket_id
                                hidden: true
                                valueFromRow: true
                              - key: new_status
                                label: 변경할 상태
                                defaultValue: pending
                                radioButtonGroup: true
                                radio:
                                  - label: 오픈
                                    value: open
                                  - label: 보류
                                    value: pending
                                  - label: 해결
                                    value: resolved
                            sql: |
                              SELECT 1

                  - type: query
                    name: 전체 타임라인
                    resource: mysql.sample
                    sqlType: select
                    showDownload: false
                    display: timeline
                    sql: |
                      SELECT *
                      FROM (
                        SELECT
                          '2026-01-21 09:55:00' AS created_at,
                          '메모' AS event_type,
                          '물류팀' AS actor,
                          '상품 파손 사진 수령' AS message
                        UNION ALL
                        SELECT
                          '2026-01-21 10:12:00',
                          '상태변경',
                          'CS팀',
                          '오픈 → 보류'
                        UNION ALL
                        SELECT
                          '2026-01-21 10:30:00',
                          '메모',
                          'CS팀',
                          '고객에게 교환 안내 완료'
                        UNION ALL
                        SELECT
                          '2026-01-21 11:40:00',
                          '상태변경',
                          'CS팀',
                          '보류 → 해결'
                      ) x
                      ORDER BY x.created_at DESC
                    params:
                      - key: ticket_id
                        valueFromRow: true
                    timelineOptions:
                      useColumn: created_at
                      template: |
                        <div style="display:flex; gap:8px; align-items:center;">
                          <span><b>{{event_type}}</b></span>
                          <span style="color:#666;">{{actor}}</span>
                        </div>
                        <div style="margin-top:4px;">{{message}}</div>